Back to skill

Security audit

DuoPlus AI

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed DuoPlus cloud-phone automation client with powerful device-control features, but its artifacts are coherent, user-directed, and include meaningful guardrails.

Install only if you intend to let an agent control DuoPlus cloud phones. Provide the DuoPlus API key only for tasks you authorize, review shell-command requests carefully, and be aware that power-on, proxy changes, app interactions, and screenshots affect the remote phone and may expose sensitive on-device content.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill clearly instructs use of network access, environment variables, and file output, but it does not declare any explicit tool scope or permissions boundary. In an agent runtime, that mismatch can cause overbroad execution authority, make review harder, and allow sensitive actions such as API calls, secret handling, and screenshot/file creation without an auditable least-privilege declaration.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The default prompt uses broad language ('manage and automate a cloud phone') that can match a wide range of ordinary user requests without clearly constraining when the skill should be invoked. In this skill’s context, invocation exposes powerful capabilities over remote Android devices, including UI control and authorized shell-command execution, so over-broad triggering increases the chance of unintended high-privilege actions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The reference specifies a fixed language header of zh, which imposes a locale choice on all requests. Under the policy, fixed language or locale requirements should either be user-selectable or clearly justified as region-specific; this document does neither.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The parser sets --lang to zh by default, which imposes a specific language/locale on API interactions unless the user explicitly overrides it. This is a natural-language locale policy issue because the skill does not present language choice as opt-in or justify the default as region-specific.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/duoplus_ai.py (reported line 1019)May include surrounding context.

python
("group_id", "group_id"),
            ("proxy_id", "proxy_id"),
        ):
            value = getattr(args, source)
            if value is not None:
                filters[target] = value
        response = client.all_phones(filters) if args.all else client.phones(filters)

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/duoplus_ai.py (reported line 1117)May include surrounding context.

python
"proxy": proxy,
        }
        for name in ("name", "dpi_name", "network_mode", "brand", "model"):
            value = getattr(args, name)
            if value is not None:
                image[name] = value
        _emit(client.control("/api/v1/cloudPhone/initProxy", {"images": [image]}))

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/control-api.md:24