Back to skill

Security audit

EngageLab OTP

Security checks for vulnerabilities and agentic risk

Overview

This looks like a real EngageLab OTP integration, but it needs Review because it handles long-lived API secrets, recipient data, and destructive template actions without enough scoping or safeguards.

Install only if you are comfortable giving an agent access to an EngageLab account that can send messages and manage OTP templates. Use environment variables or a secret manager instead of pasting dev_secret into chat, restrict the API host to EngageLab's expected endpoint, avoid logging callback payloads, and require explicit confirmation before deleting templates or sending messages to real recipients.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/otp_client.py:41
Finding

Basic Authentication credentials can be redirected to an attacker-controlled endpoint

Content
View full analysis
dict: url = f"{self._base_url}{path}" resp = requests.request(method, url, headers=self._headers, json=payload) ``` ### Technical Analysis The client accepts an arbitrary `base_url` while preparing a reusable `Authorization` header containing the Base64-encoded `dev_key:dev_secret` credential pair. Every subsequent request sends that header to the configured URL. Base64 is the encoding required by HTTP Basic Authentication; it is not encryption. Anyone who receives the header can trivially recover the original credentials. Because the client does not enforce HTTPS, validate the hostname, restrict ports, or allowlist the EngageLab API origin, an untrusted or mistakenly configured `base_url` can redirect credentials to an attacker-controlled endpoint. The default endpoint, `https://otp.api.engagelab.cc`, is consistent with the Skill's declared functionality. The vulnerability arises from permitting unrestricted endpoint replacement while automatically attaching privileged credentials. ### Attack Path 1. A victim application initializes `EngageLabOTP` with valid EngageLab credentials. 2. An attacker influences the `base_url` constructor argument through configuration injection, an environment setting, a compromised wrapper, or unsafe user input. 3. The attacker supplies a URL such as an attacker-controlled HTTPS server or a plaintext HTTP endpoint. 4. The victim calls any c ...[truncated 1062 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/verify_callback.py:34
Finding

Callback signature verification does not prevent replay attacks

Content
View full analysis
Optional[dict]: """ Parse the X-CALLBACK-ID header into its components. Header format: timestamp={ts};nonce={nonce};username={user};signature={sig} Returns dict with keys: timestamp, nonce, username, signature. Returns None if the header cannot be parsed. """ parts = {} for segment in header.split(";"): if "=" not in segment: return None key, value = segment.split("=", 1) parts[key.strip()] = value.strip() required = {"timestamp", "nonce", "username", "signature"} if not required.issubset(parts.keys()): return None return parts def compute_signature(secret: str, timestamp: str, nonce: str, username: str) -> str: """Compute HMAC-SHA256 signature matching EngageLab's algorithm.""" message = f"{timestamp}{nonce}{username}" return hmac.new( key=secret.encode(), msg=message.encode(), digestmod=hashlib.sha256, ).hexdigest() def verify_engagelab_callback(header: str, secret: str) -> bool: """ Verify an EngageLab OTP callback request. Args: header: The value of the X-CALLBACK-ID HTTP header. secret: Your configured callback secret. Returns: True if the signature is valid, False otherwise. """ parsed = parse_callback_header(header) if parsed is None: return False expected = compute_signature( secret, parsed["timestamp"], parsed["nonce"], parsed["username"], ) return hmac.compare_digest(expected, parsed["signature"]) ``` ### Technical Analysis The implementation correctly uses HMAC-SHA256 and `hmac.compare_digest()` for constant-time signature comp ...[truncated 2351 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:56
Finding

Skill instructions encourage users to disclose long-lived API secrets in Agent conversations

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The code substantially matches much of the declared purpose: it authenticates to EngageLab OTP APIs and supports OTP send, custom OTP send, OTP verification, custom message sending, and template management. However, the description explicitly claims additional capabilities that are not implemented in the supplied code chunk: callback webhook configuration and SMPP integration. There is also no explicit code for channel-specific management beyond passing template configurations to the API, though the API may support multi-channel use indirectly. Because the declared description presents these missing capabilities as covered by the skill, this is a description-to-behavior mismatch, albeit a partial one rather than a completely different purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

There is a clear description-behavior mismatch. The declared purpose presents a full-featured EngageLab OTP platform integration covering message sending, OTP verification, template management, callback configuration, and SMPP. The supplied code chunk is narrowly scoped to one supporting utility: validating webhook callback signatures for incoming requests. While callback verification is adjacent to 'callback configuration,' this code does not configure webhooks or implement the broad OTP operations described. Its primary purpose is materially narrower and different from the declared skill behavior.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
84% confidence
Finding

The skill exposes a destructive delete capability for templates without any visible guardrails such as confirmation prompts, authorization checks, or warnings about irreversible impact. In an agent workflow, a user request could be misinterpreted or prompt-injected into deleting production OTP templates, causing service disruption or weakening authentication flows.

Content

Scanner excerpt · SKILL.md (reported line 314)May include surrounding context.

md
**Get details** — `GET /v1/template-configs/:templateId` (returns full template with channel configs)

**Delete** — `DELETE /v1/template-configs/:templateId`

### Template Status

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/template-api.md (reported line 163)May include surrounding context.

md
## 2. Delete Template

`DELETE /v1/template-configs/:templateId`

The `{templateId}` in the URL is the custom template ID defined when creating the template.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill clearly facilitates outbound network access to a third-party OTP service but does not declare any tool scope or allowed-tools restrictions. In an agent environment, missing explicit network permission boundaries can let the skill be invoked without adequate review of what data may be transmitted externally.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation phrases are overly broad and include generic terms like 'send otp' and 'verification code', which can cause the skill to trigger for unrelated requests. In an agent setting, that increases the chance of routing users into a third-party integration that sends sensitive contact data or auth-related content externally when they did not specifically ask for EngageLab.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill instructs users to send OTPs, custom messages, and callback data through a third-party service but does not prominently warn that recipient phone numbers, email addresses, message content, and verification metadata will be transmitted off-platform. This creates a privacy and consent risk, especially because OTP workflows commonly involve sensitive authentication events.

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 · SKILL.md (reported line 380)May include surrounding context.

md
}

# Step 1: Send OTP
send_resp = requests.post(f"{BASE_URL}/v1/messages", headers=headers, json={
    "to": "+6591234567",
    "template": {"id": "my-template", "language": "default"}
})

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 · SKILL.md (reported line 388)May include surrounding context.

md
message_id = result["message_id"]

# Step 2: Verify OTP (after user enters the code)
verify_resp = requests.post(f"{BASE_URL}/v1/verifications", headers=headers, json={
    "message_id": message_id,
    "verify_code": "123456"
})

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · references/callback-config.md (reported line 26)May include surrounding context.

Validation request:

bash
curl -X POST https://your-callback-url.com -d ''

Required response: HTTP 200 with empty body.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation includes callback examples containing sensitive operational and personal data such as phone numbers, email addresses, IP addresses, API keys, and message contents, but it does not warn implementers to avoid logging, redistributing, or exposing these fields. In an OTP/webhook context, this increases the chance that users will copy these payloads into logs or downstream systems without redaction, leading to leakage of PII, secrets, and security telemetry.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This markdown file documents a DELETE operation for removing templates, but it does not include any warning that the action is destructive or may permanently remove configuration. For markdown files, destructive behaviors that could affect user data or system integrity should be accompanied by an explicit warning.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The client performs outbound network requests using Basic authentication headers constructed from the developer key and secret, and sends OTP-related data to a remote API. While the file has general docstrings, it does not explicitly warn users that credentials and recipient/message data will be transmitted off-system when these methods are called.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/otp_client.py (reported line 99)May include surrounding context.

python
params: Optional[dict] = None,
    ) -> dict:
        """
        Send a user-generated OTP code. No verification API call needed afterward.

        Returns dict with `message_id` and `send_channel`.
        """

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

delete_template issues a DELETE request that removes a remote template configuration, which is a destructive action. The method has a brief description, but there is no stronger warning, confirmation mechanism, or cautionary note about the impact or reversibility of the deletion.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.