Back to skill

Security audit

FreeSmsGateway

Security checks for vulnerabilities and agentic risk

Overview

The skill has a plausible SMS-gateway purpose, but it handles SMS content and credentials with weak network and webhook safeguards.

Review carefully before installing. Use only a trusted HTTPS or protected local/VPN gateway, avoid public ngrok exposure unless you add authentication, disable or tightly control OPENCLAW_WEBHOOK_URL forwarding, protect .env and .token.json permissions, and remember this skill can send SMS, read message data, and change webhook configuration.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/auth.py:75
Finding

Gateway credentials and SMS data may be transmitted over plaintext HTTP

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/auth.py:54
Finding

JWT bearer token is cached without explicit restrictive file permissions

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/webhook_server.py:9
Finding

Unauthenticated public webhook receiver forwards attacker-controlled JSON to OpenClaw

Content
View full analysis
1 else 8787 server = HTTPServer(('0.0.0.0', port), SMSWebhookHandler) print(f"🌐 SMS Webhook Receiver running on http://0.0.0.0:{port}") print(f" Forward to OpenClaw: {OPENCLAW_URL}") print(f"\nConfigure sms-gate.app webhook:") print(f" URL: http://:{port}/sms-received") print(f" Event: sms:received") print(f"\nOr with ngrok ...[truncated 2459 chars]
Remediation
View remediation
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (26)

Tainted flow: 'req' from os.environ.get (line 114, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/auth.py (reported line 88)May include surrounding context.

python
)

    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read().decode())
            _write_cached_token(data)
            return data['access_token']

Tainted flow: 'req' from os.environ.get (line 114, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/auth.py (reported line 121)May include surrounding context.

python
method=method
    )

    with urllib.request.urlopen(req, timeout=30) as resp:
        return json.loads(resp.read().decode())

Tainted flow: 'req' from os.environ.get (line 26, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
93% confidence
Finding

The server forwards full incoming SMS webhook bodies to a URL controlled by the OPENCLAW_WEBHOOK_URL environment variable without validation, restriction, or authentication. Because SMS contents often contain highly sensitive data such as OTPs, personal messages, and phone numbers, this creates a clear exfiltration path and can leak data to any endpoint configured in the environment.

Content

Scanner excerpt · scripts/webhook_server.py (reported line 32)May include surrounding context.

python
headers={'Content-Type': 'application/json'},
                        method='POST'
                    )
                    urllib.request.urlopen(req, timeout=5)
                except Exception as e:
                    print(f"   ⚠️ Could not forward to OpenClaw: {e}")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

  1. Copy the example environment file and fill in your values:
bash
cp .env.example .env
  1. Edit .env with your gateway URL and credentials:

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a broad SMS management capability, including sending messages, checking status, viewing history, and webhook management. The actual code chunk is much narrower: it only receives webhook HTTP requests, prints their contents, and optionally forwards them to a configured OpenClaw endpoint. While this partially aligns with 'manage webhooks for incoming SMS,' it does not implement the other central described capabilities. Additionally, forwarding incoming webhook data to another service is a network behavior not mentioned in the description. Therefore the code chunk does not accurately represent the full declared purpose.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api.md (reported line 54)May include surrounding context.

text
GET    /webhooks
POST   /webhooks        {"event": "sms:received", "url": "https://example.com"}
DELETE /webhooks/{event}

Webhook events:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/auth.py (reported line 17)May include surrounding context.

python
def _load_env():
    """Load .env from the skill root directory."""
    env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.env')
    if os.path.exists(env_path):
        with open(env_path) as f:
            for line in f:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/test_sms_gateway.py (reported line 20)May include surrounding context.

python
def _load_env():
    """Load .env from the skill root directory."""
    env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.env')
    if os.path.exists(env_path):
        with open(env_path) as f:
            for line in f:

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code sources a destination URL from an environment variable and uses it to forward incoming SMS webhook contents, enabling transmission to an arbitrary endpoint. In the context of an SMS gateway, this is especially dangerous because the forwarded payload may contain sensitive communications and verification codes, making the behavior functionally equivalent to data exfiltration if misused or misconfigured.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/auth.py (reported line 11)May include surrounding context.

python
#!/usr/bin/env python3
"""Integration tests for SMS Gateway skill.

Requires SMS_GATE_URL, SMS_GATE_USER, and SMS_GATE_PASS in .env or environment.
Tests call the actual scripts in scripts/ as subprocesses.
"""
import json

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/auth.py (reported line 16)May include surrounding context.

python
#!/usr/bin/env python3
"""Integration tests for SMS Gateway skill.

Requires SMS_GATE_URL, SMS_GATE_USER, and SMS_GATE_PASS in .env or environment.
Tests call the actual scripts in scripts/ as subprocesses.
"""
import json

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/auth.py (reported line 27)May include surrounding context.

python
#!/usr/bin/env python3
"""Integration tests for SMS Gateway skill.

Requires SMS_GATE_URL, SMS_GATE_USER, and SMS_GATE_PASS in .env or environment.
Tests call the actual scripts in scripts/ as subprocesses.
"""
import json

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/test_sms_gateway.py (reported line 4)May include surrounding context.

python
#!/usr/bin/env python3
"""Integration tests for SMS Gateway skill.

Requires SMS_GATE_URL, SMS_GATE_USER, and SMS_GATE_PASS in .env or environment.
Tests call the actual scripts in scripts/ as subprocesses.
"""
import json

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/test_sms_gateway.py (reported line 19)May include surrounding context.

python
#!/usr/bin/env python3
"""Integration tests for SMS Gateway skill.

Requires SMS_GATE_URL, SMS_GATE_USER, and SMS_GATE_PASS in .env or environment.
Tests call the actual scripts in scripts/ as subprocesses.
"""
import json

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README explicitly instructs users to expose an incoming-SMS webhook via ngrok or a LAN-accessible HTTP endpoint, but it does not warn that SMS contents and sender numbers will be transmitted to that endpoint. This creates a real confidentiality risk because users may unintentionally forward sensitive inbound messages to a public internet URL or an unauthenticated local listener, increasing the chance of interception, logging leakage, or misdelivery.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill requires environment secrets and instructs use of Python scripts, networking, file access, and shell commands, but it does not declare any explicit tool scope or permission boundaries. That creates an over-privileged execution model where an agent may invoke broader capabilities than users expect, increasing the chance of secret exposure, unintended network access, or misuse of local resources.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The documentation encourages sending SMS content and managing message operations without clearly warning that phone numbers, message text, and delivery metadata are sensitive data. Users may disclose personal or regulated information through the skill without understanding the privacy implications or retention/exposure risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The webhook instructions recommend exposing inbound SMS via ngrok or other remotely reachable endpoints, but they do not clearly warn that incoming message contents may be transmitted through third-party infrastructure or exposed to the public internet. Because SMS messages often contain highly sensitive data such as OTPs, personal messages, or account notifications, this omission materially increases the risk of interception, misconfiguration, or unintended disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This markdown file describes behaviors that transmit phone numbers, message contents, and webhook data over network endpoints, including outbound SMS and callback URLs. It does not include any warning about handling personal data, message disclosure, or the privacy/system implications of configuring webhooks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The code writes a bearer token cache to .token.json in the skill root without setting restrictive file permissions or protecting the location. On multi-user systems or permissive environments, another local user or process could read the cached token and use it to access SMS read/send capabilities until expiry.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code reads SMS_GATE_USER and SMS_GATE_PASS, constructs a Basic Authorization header, and transmits those credentials to a remote /auth/token endpoint. While network authentication is part of the helper's purpose, the file does not provide any user-facing notice that local credentials will be sent to an external service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
80% confidence
Finding

This code retrieves message data from an external API and later displays sender phone numbers and message text. While the module docstring says it checks for incoming SMS, it does not explicitly warn that private message contents and identifiers will be fetched and surfaced to the user, which is a user-data/privacy-relevant behavior under the warning rule.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The webhook receiver performs an additional data-forwarding function beyond simply receiving local SMS gateway webhooks, expanding the skill’s behavior beyond its stated role. That mismatch matters because it silently redistributes inbound SMS data to another service, increasing data exposure and trust boundary violations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file forwards webhook payloads onward without any in-file warning, consent flow, or disclosure that inbound SMS data will be retransmitted. Lack of transparency around secondary handling of sensitive SMS data increases the chance of unnoticed privacy violations and unsafe deployment by users who assume the tool is only local.

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 · tests/test_sms_gateway.py (reported line 43)May include surrounding context.

python
def run_script(script_name, args=None):
    """Run a script from scripts/ and return (stdout, stderr, returncode)."""
    cmd = ['python3', os.path.join(SCRIPTS_DIR, script_name)] + (args or [])
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.stdout.strip(), result.stderr.strip(), result.returncode