Back to skill

Security audit

focusavatar

Security checks for vulnerabilities and agentic risk

Overview

The skill appears aligned with a FocusAvatar video-generation service, but it can send API credentials to an environment-configured endpoint, which users should review before installing.

Install only if you intend to use FocusAvatar and are comfortable sending the supplied media/text plus API credentials to its backend. Keep FOCUSAVATAR_API unset unless you deliberately trust the alternate endpoint, use least-privilege or disposable credentials if available, and watch for broad invocations that may submit jobs without an explicit FocusAvatar request.

Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • 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)

Tainted flow: 'headers' from os.environ.get (line 105, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
headers = make_auth_headers(access_key_id, access_key_secret)
        try:
            payload = {"mp3": mp3, "mp4": mp4, "text": text}
            resp = requests.post(
                API_ENDPOINT.rstrip("/") + "/skill/api/submit",
                json=payload,
                headers=headers,
Confidence
94% confidence
Finding
The script sends accessKeyId/accessKeySecret in HTTP headers to a network endpoint whose base URL is overridable via the FOCUSAVATAR_API environment variable. That means anyone able to influence the runtime environment can redirect authenticated requests to an attacker-controlled host and exfiltrate credentials. In a skill/agent context, transmitting user-supplied secrets off-box is expected for the advertised service, but allowing the destination host to be changed without validation materially increases the risk.

Tainted flow: 'status_url' from os.environ.get (line 148, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
while True:
            try:
                poll_count += 1
                r = requests.post(
                    status_url,
                    json={"orderNo": task_id},
                    headers=headers,
Confidence
93% confidence
Finding
The polling request reuses the same authentication headers and sends them to status_url derived from the same environment-controlled API endpoint. If FOCUSAVATAR_API is tampered with, the repeated polling loop will continue sending credentials to an attacker-controlled server, increasing exposure. The very long timeout and retry behavior make credential leakage more persistent once misconfigured.

Tainted flow: 'url' from os.environ.get (line 210, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
def query_result(order_no: str, key_id: str, key_secret: str):
            url = API_ENDPOINT.rstrip("/") + "/skill/api/api/result"
            h = make_auth_headers(key_id, key_secret)
            r = requests.post(url, json={"orderNo": order_no}, headers=h, timeout=30)
            r.raise_for_status()
            # 处理返回:如果是字符串就解析,已经是 dict 直接用
            raw = r.json()
Confidence
92% confidence
Finding
The inline query_result helper posts orderNo along with authentication headers to a URL built from the environment-controlled API endpoint. This creates the same credential exfiltration path during result lookup if an attacker can set or influence FOCUSAVATAR_API. Because this path is simpler and likely to be reused, it is a real secret-leak risk rather than a mere theoretical taint flow.

Tainted flow: 'RESULT_URL' from os.environ.get (line 12, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
"""
    headers = _auth_headers(access_key_id, access_key_secret)
    payload = {"orderNo": order_no}
    r = requests.post(RESULT_URL, json=payload, headers=headers, timeout=30)
    r.raise_for_status()
    raw = r.json()
    return json.loads(raw) if isinstance(raw, str) else raw
Confidence
92% confidence
Finding
The request destination is taken from the FOCUSAVATAR_API environment variable and used directly in requests.post while authentication headers include the access key ID and secret. If an attacker can influence the environment, they can redirect this request to an arbitrary host and exfiltrate credentials and order data, creating an SSRF-style outbound credential leak. The skill context increases severity because this script is explicitly designed to send secrets in headers.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill documentation clearly indicates it uses environment variables for credentials and makes outbound network requests to a configurable backend, yet no permissions are declared. This creates a transparency and consent problem: users or hosting platforms may not realize the skill can read secrets from the environment and transmit user-supplied data plus authentication headers to a remote service.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The trigger list contains broad terms such as general video-generation and speech-related phrases that can match ordinary user requests beyond the skill's intended scope. This can cause unintended invocation of a credentialed external API skill, increasing the chance of surprise actions, data being sent to a third-party backend, or users being routed into this tool when they did not explicitly request it.

Static analysis

No suspicious patterns detected.