Back to skill

Security audit

AgentsMakingFriends

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real A2A bridge, but its server can expose the local main OpenClaw agent over the network with unsafe defaults and weak secret handling.

Review carefully before installing. Do not run the server as documented on a public or shared network; use localhost or a protected network, require authentication and TLS, avoid storing tokens in workspace docs, prevent token logging, and route remote requests to a constrained low-privilege agent rather than the main agent.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/a2a_server.py:37
Finding

Unauthenticated Network Exposure of the Privileged Main Agent

Content
View full analysis

Vulnerability Details

File Location: scripts/a2a_server.py:37-43, scripts/a2a_server.py:111-174, scripts/a2a_server.py:207
Vulnerability Type: Missing authentication and violation of least privilege
Risk Level: Critical

Vulnerable Code

python
def check_auth(self) -> bool:
    if not self.required_token:
        return True
    auth_header = self.headers.get('Authorization', '')
    if auth_header.startswith('Bearer '):
        return auth_header[7:] == self.required_token
    return False
python
def handle_message_send(self, params: Dict[str, Any], request_id: str) -> Dict[str, Any]:
    message = params.get('message', {})
    parts = message.get('parts', [])
    
    # Extract text
    text = ""
    for part in parts:
        if part.get('type') == 'text':
            text = part.get('text', '')
            break
    
    if not text:
        return {
            "jsonrpc": "2.0",
            "error": {"code": -32602, "message": "No text in message"},
            "id": request_id
        }
    
    # Call OpenClaw agent
    print(f"[A2A] Received: {text}")
    
    try:
        result = subprocess.run(
            ['openclaw', 'agent', '--agent', 'main', '--message', text, '--json'],
            capture_output=True,
            text=True,
            timeout=120
        )
        
        if result.returncode == 0:
            try:
                agent_response = json.loads(result.stdout)
                response_text = agent_response.get('content', result.stdout)
            except json.JSONDecodeError:
                response_text = result.stdout
        else:
            response_text = f"Error: {result.stderr}"
        
        print(f"[A2A] Response: {response_text[:100]}...")
        
    except subprocess.TimeoutExpired:
        response_text = "Error: Agent timeout"
    except Exception as e:
       
...[truncated 2026 chars]
Remediation
View remediation

Remediation Suggestions

  • Require authentication by default and refuse to start without an authentication configuration when binding to a non-loopback address.
  • Bind to 127.0.0.1 by default; require an explicit secure option to bind to external interfaces.
  • Route remote requests to a dedicated least-privileged agent rather than main.
  • Disable command execution, unrestricted file access, secret access, and other high-risk tools for the remote-facing agent.
  • Add an authorization policy that limits callers to explicitly approved capabilities.
  • Require user approval before performing sensitive operations initiated by remote messages.
  • Use a constant-time token comparison and support token rotation, expiration, and revocation.
  • Add request rate limits, audit logging, and network-level access controls.
  • Change the documented quick start to a secure authenticated configuration.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/a2a_client.py:24
Finding

Bearer Tokens and Agent Messages Can Be Transmitted over Plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: scripts/a2a_client.py:24-27, scripts/a2a_client.py:30-42, scripts/a2a_client.py:45-68; insecure HTTP usage is also documented in SKILL.md:16-19 and SKILL.md:48-55
Vulnerability Type: Plaintext transmission of sensitive information
Risk Level: High

Vulnerable Code

python
def __init__(self, agent_url: str, token: Optional[str] = None):
    self.agent_url = agent_url.rstrip('/')
    self.headers = {'Content-Type': 'application/json'}
    if token:
        self.headers['Authorization'] = f'Bearer {token}'
python
def get_agent_card(self) -> Dict[str, Any]:
    """Get Agent Card (discover agent capabilities)"""
    url = f"{self.agent_url}/.well-known/agent.json"
    req = urllib.request.Request(url, headers=self.headers)
    
    try:
        with urllib.request.urlopen(req, timeout=30) as response:
            return json.loads(response.read().decode('utf-8'))
    except urllib.error.HTTPError:
        # Try alternate path
        url = f"{self.agent_url}/agent-card"
        req = urllib.request.Request(url, headers=self.headers)
        with urllib.request.urlopen(req, timeout=30) as response:
            return json.loads(response.read().decode('utf-8'))
python
def send_message(self, message: str, context_id: Optional[str] = None) -> Dict[str, Any]:
    """Send message to remote agent (JSON-RPC 2.0)"""
    request_body = {
        "jsonrpc": "2.0",
        "method": "message/send",
        "id": "1",
        "params": {
            "message": {
                "role": "user",
                "parts": [{"type": "text", "text": message}]
            }
        }
    }
    
    if context_id:
        request_body["params"]["contextId"] = context_id
    
    req = urllib.request.Request(
        f"{self.agent_url}/rpc",
        data=json.dumps(request_body).encode('utf-8'),
        heade
...[truncated 2056 chars]
Remediation
View remediation

Remediation Suggestions

  • Require https:// for all non-loopback destinations.
  • Reject plaintext URLs before constructing or sending a request.
  • Permit HTTP only through an explicit development-only override restricted to loopback addresses.
  • Retain normal certificate and hostname verification; do not add insecure TLS-bypass options.
  • Update SKILL.md, agent_card.json, usage strings, and API examples to use HTTPS exclusively.
  • Avoid sending authorization credentials during unauthenticated capability discovery unless the endpoint explicitly requires them.
  • Apply strict redirect policies so credentials cannot be forwarded to an unintended destination.
  • Use short-lived, narrowly scoped credentials and rotate any token that may have crossed plaintext HTTP.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/a2a_server.py:209
Finding

Bearer Tokens Are Exposed through Command-Line Arguments, Plaintext Configuration, and Server Logs

Content
View full analysis

Vulnerability Details

File Location: scripts/a2a_client.py:102-106, scripts/a2a_server.py:195-199, scripts/a2a_server.py:209-212, and SKILL.md:48-55
Vulnerability Type: Insecure secret handling
Risk Level: High

Vulnerable Code

python
agent_url = sys.argv[1]
message = sys.argv[2]
token = sys.argv[3] if len(sys.argv) > 3 else None

client = A2AClient(agent_url, token)
python
parser = argparse.ArgumentParser(description='A2A Server for OpenClaw Agent')
parser.add_argument('--port', type=int, default=8080, help='Server port (default: 8080)')
parser.add_argument('--token', type=str, help='Bearer Token (optional)')
parser.add_argument('--name', type=str, default='OpenClaw Agent', help='Agent name')
parser.add_argument('--description', type=str, default='OpenClaw Personal AI Assistant', help='Agent description')
args = parser.parse_args()
python
print(f"🦞 A2A Server started!")
print(f"📍 URL: http://0.0.0.0:{args.port}")
print(f"📋 Agent Card: http://0.0.0.0:{args.port}/.well-known/agent.json")
print(f"🔐 Auth: {'Bearer Token: ' + args.token if args.token else 'No auth'}")

The documentation also recommends plaintext token storage:

markdown
### A2A Agents

- Remote Agent Name:
  URL: http://1.2.3.4:8080/a2a
  Token: your-bearer-token

Technical Analysis

Both client and server accept bearer tokens as process arguments. Process command lines may be visible in process listings, monitoring systems, shell history, diagnostics, or job-runner metadata. The server additionally prints the complete token to standard output, which can be captured by terminals, service managers, centralized logging systems, or CI logs.

The configuration example recommends placing the token directly in TOOLS.md, where it may be accessible to workspace readers or accidentally committed, synchronized, backed up, or included in diagnostic bundles.

Attack P

...[truncated 876 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove positional and --token command-line secret arguments.
  • Read tokens from a secret manager, an interactive hidden prompt, or a permission-restricted file descriptor.
  • If environment variables are supported, document their exposure limitations and prefer a dedicated secret manager for production.
  • Never print a token or any reversible portion of it; log only whether authentication is enabled.
  • Redact authorization headers and tokens from diagnostics and exception output.
  • Do not store credentials in TOOLS.md or other general workspace documentation.
  • Store secret files outside the repository with owner-only permissions.
  • Use scoped, short-lived tokens with rotation and revocation support.
  • Rotate any credentials previously passed through process arguments or emitted to logs.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/a2a_server.py:66
Finding

Unbounded Request Body Read Allows Remote Denial of Service

Content
View full analysis

Vulnerability Details

File Location: scripts/a2a_server.py:66-80
Vulnerability Type: Missing request-size validation and resource exhaustion
Risk Level: High

Vulnerable Code

python
def do_POST(self):
    if not self.check_auth():
        self.send_json_response({"error": "Unauthorized"}, 401)
        return
    
    content_length = int(self.headers.get('Content-Length', 0))
    body = self.rfile.read(content_length).decode('utf-8')
    
    try:
        request = json.loads(body)
    except json.JSONDecodeError:
        self.send_json_response({
            "jsonrpc": "2.0",
            "error": {"code": -32700, "message": "Parse error"},
            "id": None
        })
        return

The server is instantiated with the single-threaded implementation:

python
server = HTTPServer(('0.0.0.0', args.port), OpenClawA2AHandler)

Technical Analysis

The server converts the attacker-controlled Content-Length header to an integer and passes it directly to read() without imposing a maximum request size. A client can request an extremely large allocation or slowly transmit a declared body while the server waits for completion.

This behavior is amplified by the use of Python's single-threaded HTTPServer: one slow or oversized request can prevent the server from processing other clients. Invalid nonnumeric Content-Length values may also raise an uncaught ValueError, terminating the individual request unexpectedly.

Attack Path

  1. An attacker connects to the externally bound HTTP service.
  2. If authentication is disabled, no credentials are needed; if enabled, any authorized or compromised caller can perform the same attack.
  3. The attacker submits a POST request with an extremely large Content-Length, or sends the body very slowly.
  4. The handler blocks while reading the declared number of bytes or consumes excessive memory while storing the bo ...[truncated 615 chars]
Remediation
View remediation

Remediation Suggestions

  • Define a strict maximum request-body size appropriate for text A2A messages.
  • Validate that Content-Length is present, numeric, nonnegative, and below the configured limit.
  • Return HTTP 411 for missing required lengths, HTTP 400 for malformed lengths, and HTTP 413 for oversized requests.
  • Apply socket and request-read timeouts to mitigate slow-request attacks.
  • Avoid reading the entire body before validation where streaming or bounded reads are possible.
  • Use a production-grade HTTP server or reverse proxy with body-size limits, connection limits, concurrency controls, and timeouts.
  • Add per-client rate limiting and total request quotas.
  • Keep authentication mandatory, while recognizing that authentication alone does not replace resource limits.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (10)

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

Scanner excerpt · scripts/a2a_client.py (reported line 44)May include surrounding context.

python
return json.loads(response.read().decode('utf-8'))
    
    def send_message(self, message: str, context_id: Optional[str] = None) -> Dict[str, Any]:
        """Send message to remote agent (JSON-RPC 2.0)"""
        request_body = {
            "jsonrpc": "2.0",
            "method": "message/send",

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises and instructs use of network and shell-capable scripts but does not declare any tool scope or permission boundaries. In an agent environment, this increases the chance that the skill is invoked with broader-than-expected capabilities, making misuse, unintended outbound connections, or unsafe command execution harder to govern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill recommends exposing OpenClaw as a network-accessible A2A service without any warning about authentication, authorization, network trust boundaries, or attack surface. Because this service is specifically designed for inter-agent task execution, exposing it insecurely could permit unauthorized requests, prompt injection relay, abuse of connected tools, or broader compromise of the host agent environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documentation tells users to place a bearer token directly in TOOLS.md, which encourages storing secrets in a likely plaintext, shareable, and version-controllable file. That raises the risk of credential leakage through logs, screenshots, backups, repository commits, or downstream agent/tool exposure, enabling unauthorized access to remote agents.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The agent card advertises an 'execute' capability even though this service is presented as an A2A communication bridge. Advertising generic execution broadens perceived authority and may cause remote agents or orchestrators to invoke the service for command-like actions, increasing the chance of unsafe use or over-trust.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The server accepts remote JSON-RPC requests and directly forwards attacker-supplied text into the local OpenClaw agent, effectively exposing the host's agent functionality over the network. In this skill context, that is especially dangerous because the bridge can enable untrusted remote agents to drive a local agent that may have broader tools, data access, or side effects than the A2A wrapper suggests.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/a2a_server.py (reported line 150)May include surrounding context.

python
print(f"[A2A] Received: {text}")
        
        try:
            result = subprocess.run(
                ['openclaw', 'agent', '--agent', 'main', '--message', text, '--json'],
                capture_output=True,
                text=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The startup log prints the full bearer token to stdout, which can leak secrets into terminal history, logs, process supervisors, container logs, or monitoring systems. Anyone who obtains that token can authenticate to the exposed A2A service and remotely invoke the local agent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest advertises broad, unconstrained capabilities such as general conversation, task execution, and various operations without clearly defining limits, authorization requirements, or safety boundaries. In an A2A context, vague capability descriptions increase the risk that remote agents or users will over-trust the service and invoke sensitive actions that were not clearly disclosed or scoped.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest explicitly exposes an "execute" skill that can run shell commands and process files, but it provides no warning about the potential for system modification, data access, or destructive side effects. Because this is an A2A service intended for remote agent-to-agent use, under-disclosing system-impacting behavior is especially dangerous: other agents may invoke it without sufficient safeguards, creating a path to remote command execution and sensitive file abuse.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.