Back to skill

Security audit

Omni Channel Agent

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its market-research purpose, but it handles credentials too broadly and includes unsafe product-opportunity content that needs review before installation.

Review before installing. Use dedicated, least-privilege API tokens, avoid relying on ~/.bashrc credential loading, do not run it as an elevated user, and remove or filter adult, nudification, and creator-likeness reuse outputs before using the reports for product decisions.

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)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
run_pipeline.py:24
Finding

Automatic Credential Discovery and Over-Broad Subprocess Environment Inheritance

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
apify_client.py:94
Finding

API Credentials Exposed in URL Query Strings

Content
View full analysis
list: """ Run actor using Apify's synchronous endpoint (waits for result in single call). Better for quick actors (< 2 min). """ if not APIFY_TOKEN: raise ValueError("APIFY_TOKEN environment variable not set") print(f"[Apify] Running actor (sync): {actor_id}") url = f"{APIFY_BASE}/acts/{actor_id}/run-sync-get-dataset-items?token={APIFY_TOKEN}&timeout={timeout_secs}" body = json.dumps(input_data).encode() req = urllib.request.Request(url, data=body, headers={"Content-Type": "application/json"}) try: with urllib.request.urlopen(req, timeout=timeout_secs + 30) as resp: items = json.loads(resp.read().decode()) print(f"[Apify] Got {len(items)} items (sync)") return items except urllib.error.HTTPError as e: error_body = e.read().decode() if e.fp else "" print(f"[Apify] Sync run failed: HTTP {e.code}: {error_body[:300]}") return [] except Exception as e: print(f"[Apify] Sync run error: {e}") return [] ``` The active SEO pipeline uses the same pattern for Semrush: ```python url = (f"https://api.semrush.com/?type=domain_organic&key={SEMRUSH_KEY}" f"&display_limit={limit}&export_columns=Ph,Po,Nq,Cp,Co,Kd,Tr,Tc,Ur" f"&domain={domain}&database={database}") try: resp = urllib.request.urlopen(url, timeout=20) ``` The standalone full-research script places a Facebook token in its query parameters: ...[truncated 2426 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
sources/facebook_ads.py:91
Finding

Predictable Shared Temporary Output Paths Permit Symlink-Based File Overwrite

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (117)

Tainted flow: 'req' from os.environ.get (line 106, 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 · apify_client.py (reported line 31)May include surrounding context.

python
body = json.dumps(data).encode() if data else None
    req = urllib.request.Request(url, data=body, headers=_headers(), method=method)
    try:
        with urllib.request.urlopen(req, timeout=60) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        error_body = e.read().decode() if e.fp else ""

Tainted flow: 'req' from os.environ.get (line 106, 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 · apify_client.py (reported line 77)May include surrounding context.

python
body = json.dumps(data).encode() if data else None
    req = urllib.request.Request(url, data=body, headers=_headers(), method=method)
    try:
        with urllib.request.urlopen(req, timeout=60) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        error_body = e.read().decode() if e.fp else ""

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

Critical
Category
Data Flow
Confidence
91% confidence
Finding

The synchronous execution path places APIFY_TOKEN directly into the request URL query string. Secrets in URLs are commonly exposed through logs, proxies, monitoring systems, browser/history equivalents, and upstream infrastructure, making credential leakage much more likely than if the token were sent only in an Authorization header.

Content

Scanner excerpt · apify_client.py (reported line 109)May include surrounding context.

python
req = urllib.request.Request(url, data=body, headers={"Content-Type": "application/json"})
    
    try:
        with urllib.request.urlopen(req, timeout=timeout_secs + 30) as resp:
            items = json.loads(resp.read().decode())
            print(f"[Apify] Got {len(items)} items (sync)")
            return items

Tainted flow: 'url' from os.environ.get (line 124, 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 · sources/seo_full_research.py (reported line 103)May include surrounding context.

python
f"&display_limit={limit}&export_columns=Ph,Po,Nq,Cp,Co,Kd,Tr,Tc,Ur"
           f"&domain={domain}&database={db}")
    try:
        resp = urllib.request.urlopen(url, timeout=15)
        text = resp.read().decode()
        if 'ERROR' in text:
            return []

Tainted flow: 'url' from os.environ.get (line 124, 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 · sources/seo_full_research.py (reported line 125)May include surrounding context.

python
'limit': 25,
        })
        url = f"https://graph.facebook.com/v21.0/ads_archive?{params}"
        resp = urllib.request.urlopen(url, timeout=10)
        data = json.loads(resp.read().decode())
        if 'data' in data:
            ads = data['data']

Tainted flow: 'req' from os.environ.get (line 136, 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 · sources/seo_pipeline.py (reported line 80)May include surrounding context.

python
try:
        headers = {'User-Agent': 'Mozilla/5.0 (compatible; MyShellBot/1.0)'}
        req = urllib.request.Request(SITEMAP_URL, headers=headers)
        resp = urllib.request.urlopen(req, timeout=15)
        index_xml = resp.read().decode()
        sub_urls = re.findall(r'<loc>(https://art\.myshell\.ai/[^\s<]+\.xml)</loc>', index_xml)
        slugs = set()

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

Critical
Category
Data Flow
Confidence
98% confidence
Finding

The Semrush API key is embedded in the request URL query string and transmitted to an external service. Although this is part of the intended functionality, putting secrets in URLs is risky because URLs are often logged by proxies, monitoring tools, exception traces, and server access logs, increasing the chance of credential disclosure.

Content

Scanner excerpt · sources/seo_pipeline.py (reported line 115)May include surrounding context.

python
f"&display_limit={limit}&export_columns=Ph,Po,Nq,Cp,Co,Kd,Tr,Tc,Ur"
           f"&domain={domain}&database={database}")
    try:
        resp = urllib.request.urlopen(url, timeout=20)
        text = resp.read().decode()
        if 'ERROR' in text[:100]:
            print(f"[SEO] Semrush error for {domain}: {text[:100]}")

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

Critical
Category
Data Flow
Confidence
94% confidence
Finding

The code sends a bearer token from the environment to Notion over the network. This is expected for API use, but it still represents transmission of a high-value credential to an external service, and compromise of the runtime, logs, or request instrumentation could expose the token and permit access to Notion data.

Content

Scanner excerpt · sources/seo_pipeline.py (reported line 141)May include surrounding context.

python
"Notion-Version": "2022-06-28",
            "Content-Type": "application/json",
        })
        with urllib.request.urlopen(req, timeout=15) as resp:
            result = json.loads(resp.read().decode())
        
        bot_names = set()

Tainted flow: 'url' from os.environ.get (line 69, 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 · sources/seo_semrush.py (reported line 73)May include surrounding context.

python
f"&display_limit={limit}&export_columns=Ph,Po,Nq,Cp,Co,Kd,Tr,Tc,Ur"
           f"&domain={domain}&database={database}")
    try:
        resp = urllib.request.urlopen(url, timeout=15)
        text = resp.read().decode()
        if 'ERROR' in text:
            return []

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

声明描述的是一个覆盖社媒端、SEO端、投放端的“全渠道选品 Agent”,核心价值应是跨渠道汇总信息用于选品判断。实际代码则专注于 Facebook Ads Library 数据抓取与分析,且具体只覆盖投放端中的 Facebook 广告场景:活跃广告、视频素材、图片素材、文案模式与 CTA 分布。代码中没有任何社媒热点、SEO 调研、TikTok 趋势或跨渠道融合逻辑,也没有体现“确定待上线需求”的选品决策流程。虽然声明中提到了“竞品广告”“Facebook Ads”,这些与代码部分吻合,但代码能力只是声明大范围能力中的一个子集,且主功能比声明明显更窄、更单一,因此构成描述与行为的实质性不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

声明描述的是一个面向运营选品决策的综合型 agent,覆盖社媒、SEO、投放、竞品广告等多个渠道;而代码只实现了单一的 TikTok KOL 监控与趋势评分模块。其核心功能是抓取固定 KOL 账号内容、做趋势信号分析和音频聚合,虽然与“社媒热点”或“TikTok趋势”部分相关,但远不足以支撑“全渠道选品 Agent”的整体描述,也没有 SEO、Facebook Ads、竞品广告、跨渠道整合或需求上线决策逻辑。因此存在明显的描述—行为不匹配。

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The SEO corpus explicitly includes sexualized and privacy-invasive capability targets such as clothing removal, breast enlargement, jiggle, kissing, and twerk generation. In the context of a general product-selection agent, these terms can steer development, marketing, or automation toward abusive image-manipulation features, including non-consensual sexualized transformations.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Plain-language promotion of AI clothing-removal tools is strongly associated with privacy-invasive and non-consensual intimate-image abuse. In this agent context, surfacing it as an SEO opportunity risks legitimizing or operationalizing nudification-related capabilities.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The dataset contains explicit body-modification search terms centered on breasts and sexualized enhancement. In a product-research pipeline, such terms can drive unsafe roadmap decisions or ad targeting for manipulative and potentially abusive synthetic-media features.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The SEO targets include explicit sexualized keywords inappropriate for a general-purpose skill and not necessary for benign selection research. This meaningfully increases the risk that the agent will prioritize, normalize, or recommend unsafe adult-generation functionality.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Repeated breast-related AI keywords show this is not an isolated noisy term but a deliberate pattern of capturing sexualized demand. Repetition raises the chance of downstream optimization, monetization, or capability discovery around unsafe sexual-content generation.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Repeated paraphrases of clothing-removal demand show sustained collection of privacy-invasive abuse signals rather than incidental noise. This repetition can help downstream systems discover synonyms and optimize around an abusive capability category.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The presence of fetishized and sexualized body-enhancement terms indicates the dataset is collecting unsafe adult-interest signals rather than neutral market research. In this skill context, that expands harm potential toward sexual exploitation and non-consensual image manipulation features.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Multiple slang terms for breasts appear in the SEO targets, confirming explicit adult-content orientation. Slang-based capture is especially risky because it indicates intent to reach demand that often bypasses standard safety filters and moderation heuristics.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Additional explicit anatomy and breast-enhancement keywords reinforce that the corpus is tuned toward sexualized generation opportunities. This is dangerous because such inputs can influence agent recommendations, content strategy, and feature prioritization in ways that violate safety expectations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Terms related to AI lingerie and breast enlargement are incompatible with a general product-selection dataset and move the skill toward sexualized synthetic-media generation. The risk is amplified because these are framed as market opportunities rather than as abuse indicators to avoid.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Explicit breast-related slang such as 'boobies' and similar variants is clear adult-content targeting, not accidental overlap. In a skill that informs product and growth decisions, this can directly support unsafe feature discovery and inappropriate audience targeting.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The output is materially out of scope for an omni-channel product-selection agent: it is dominated by AI dance/filter trend scraping rather than balanced social/SEO/ads research tied to stated business purpose. Scope drift like this is dangerous because it drives unnecessary data collection and can hide covert or unauthorized surveillance behavior behind a legitimate-seeming skill description.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill collects Reddit posts unrelated to product selection, including explicit sexual content, which creates unnecessary exposure to sensitive and inappropriate material. This increases privacy, compliance, workplace-safety, and reputational risk, especially if the dataset is surfaced to business users or reused in downstream analytics without content controls.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The 'ai_value' fields explicitly frame creators as sources for extracting reusable AI-generation assets such as face swap inputs, pose tracking data, style copying, choreography extraction, and template creation. That goes beyond passive trend research and encourages appropriation of creator likeness, motion, and stylistic output for model or template reuse, creating significant IP, consent, and abuse risk.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.