Back to skill

Security audit

Social Intel Hub

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it advertises, but its scraped-data cache and spreadsheet export handling create review-worthy safety risks.

Install only if you are comfortable sending search terms and note IDs to the configured TikHub/mcporter services and storing scraped public content locally. Treat generated CSV/XLSX files as untrusted because social-media fields may contain spreadsheet formulas, and clear /tmp/social_intel_cache on shared machines.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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

Warning
Location
social_intel.py:381
Finding

Spreadsheet Formula Injection in CSV and Excel Exports

Content
View full analysis

Vulnerability Details

File Location: social_intel.py, lines 381-384 and 411-415
Vulnerability Type: Spreadsheet formula injection
Risk Level: Medium

Vulnerable Code

python
with open(output_path, "w", newline="", encoding="utf-8-sig") as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction="ignore")
    writer.writeheader()
    writer.writerows(notes)
python
for note in notes:
    row = [note.get(f, "") for f in fields]
    ws.append(row)
# Set column widths
ws.column_dimensions["J"].width = 50
ws.column_dimensions["K"].width = 40

Technical Analysis

Social-media fields including author, desc, and url are controlled by remote content authors. The application writes these values directly into CSV and XLSX cells without neutralizing strings beginning with spreadsheet formula characters such as =, +, -, or @.

When a generated report is opened, spreadsheet software may interpret an attacker-controlled value as a formula instead of plain text. XLSX values beginning with = are particularly likely to be stored as formulas by openpyxl. CSV behavior depends on the spreadsheet application used to open the file.

Potential payloads can reference external resources, disclose spreadsheet values through outbound requests, track report viewers, or invoke dangerous legacy spreadsheet functionality. Actual code execution depends on the spreadsheet product, platform, security configuration, and user interaction.

Attack Path

  1. An attacker publishes a social-media post, profile name, description, or URL containing a malicious spreadsheet formula.
  2. A victim searches for content that includes the attacker's record.
  3. The Skill receives the malicious field through the TikHub MCP service.
  4. The victim invokes --export csv, --export excel, or --export both.
  5. The untrusted value is written to the report without sanitization.
  6. The victim opens the generated file in spreadsheet so ...[truncated 637 chars]
Remediation
View remediation

Remediation Suggestions

  • Sanitize every remotely sourced field before CSV or Excel export.
  • Convert values to strings and prefix values beginning with =, +, -, or @ with an apostrophe.
  • For XLSX files, explicitly store untrusted values as text rather than formulas.
  • Apply protection to every exported field, including author names, descriptions, identifiers, dates, and URLs.
  • Consider rejecting control characters and normalizing leading whitespace before checking the first meaningful character.
  • Add regression tests for payloads such as =1+1, +SUM(1,1), -1+2, and @SUM(1,1).
  • Document that exported files contain third-party content and should be opened with external-link and macro protections enabled.

A centralized helper should be used by both exporters, for example:

python
def safe_spreadsheet_value(value):
    text = "" if value is None else str(value)
    stripped = text.lstrip()
    if stripped.startswith(("=", "+", "-", "@")):
        return "'" + text
    return text

T09 · Insecure Skill Coding Practices

Warning
Location
social_intel.py:87
Finding

Predictable Cache Files and Symlink-Following Writes in Shared Temporary Storage

Content
View full analysis

Vulnerability Details

File Location: social_intel.py, lines 47-50 and 87-111
Vulnerability Type: Unsafe temporary-file and cache handling
Risk Level: Medium

Vulnerable Code

python
OUTPUT_DIR = "/tmp/social_intel"
CACHE_DIR = "/tmp/social_intel_cache"
os.makedirs(OUTPUT_DIR, exist_ok=True)
os.makedirs(CACHE_DIR, exist_ok=True)
python
def get_cache_key(platform, keyword, page=1):
    raw = f"{platform}:{keyword}:{page}"
    return hashlib.md5(raw.encode()).hexdigest()


def get_from_cache(platform, keyword, page=1):
    key = get_cache_key(platform, keyword, page)
    path = os.path.join(CACHE_DIR, f"{platform}_{key}.json")
    if os.path.exists(path):
        age = time.time() - os.path.getmtime(path)
        if age < 86400:  # 24h cache
            with open(path) as f:
                return json.load(f)
    return None


def save_to_cache(platform, keyword, page, data):
    key = get_cache_key(platform, keyword, page)
    path = os.path.join(CACHE_DIR, f"{platform}_{key}.json")
    with open(path, "w") as f:
        json.dump(data, f)

Technical Analysis

The cache is stored in a fixed, shared directory under /tmp. Filenames are deterministic because they are derived from the platform, keyword, and page. MD5 provides no unpredictability and is not being used with a secret value.

The implementation does not verify directory ownership or permissions and does not check whether a cache path is a symbolic link or regular file. The open(path, "w") call follows symbolic links and truncates an existing target. Cache writes are also not atomic.

On a multi-user system, another local user who can predict a victim's query can calculate the corresponding filename and prepare a symbolic link before the cache is written. Depending on directory permissions and ownership, this can redirect the write to another file writable by the victim process. A local attacker may also attempt cache poisoning by pre-creating valid ...[truncated 1487 chars]

Remediation
View remediation

Remediation Suggestions

  • Store cache data in a private per-user cache directory rather than a global fixed directory.
  • Create the directory with mode 0700 and verify that it is owned by the current user.
  • Create cache files with restrictive permissions such as 0600.
  • Validate the platform against an explicit allow-list before using it in any path.
  • Reject symbolic links and non-regular files. Where supported, use O_NOFOLLOW.
  • Write to a securely created temporary file in the same directory, flush it, and atomically replace the final cache file with os.replace().
  • Avoid check-then-open sequences such as exists() followed by open(), because they introduce time-of-check to time-of-use races.
  • Verify cache-file ownership before reading existing data.
  • Consider using platformdirs.user_cache_dir() or another standard per-user cache facility.
  • Treat cached JSON as untrusted input and validate its structure before processing.

T08 · Insecure Dependencies

Note
Location
SKILL.md:15
Finding

Unpinned Runtime Dependencies Create Supply-Chain Exposure

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 15-21 and 129-135
Vulnerability Type: Unpinned third-party dependencies
Risk Level: Low

Vulnerable Configuration

text
"python_pkgs": ["wordcloud", "matplotlib", "openpyxl"],
text
"label": "pip3 install wordcloud matplotlib openpyxl",
bash
pip3 install wordcloud matplotlib openpyxl

Technical Analysis

The Skill instructs users to install wordcloud, matplotlib, and openpyxl without version constraints, hashes, a lockfile, or a specified trusted package index.

The package names are consistent with the libraries imported by the script, and the reviewed project contains no direct evidence that these packages are intentionally malicious or typosquatted. However, an unpinned installation resolves mutable package versions from the user's configured index. Consequently, the installed code may differ over time from the versions that were tested or reviewed.

Python package installation and import can execute package-controlled code. A compromised package release, dependency, mirror, or package-index configuration could therefore execute code outside the audited project.

Attack Path

  1. A user follows the documented pip3 install command.
  2. pip resolves the latest compatible packages and transitive dependencies from its configured index.
  3. A compromised package version, transitive dependency, or untrusted index supplies malicious code.
  4. Package-controlled code executes during installation or when the Skill imports the dependency.
  5. The malicious dependency operates with the privileges of the user running pip or the Skill.

Impact Assessment

Impact depends on the privileges used during installation and execution. Under a normal user account, a compromised dependency could access that user's files, environment variables, network credentials, and application data. If installation is performed with administrative privileges, system-wi ...[truncated 189 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin each direct and transitive dependency to a reviewed version.
  • Provide a lockfile or hashed requirements file.
  • Install with pip install --require-hashes -r requirements.txt.
  • Document the expected trusted package index and avoid unspecified private or fallback indexes.
  • Use an isolated virtual environment rather than installing packages globally.
  • Regularly scan pinned packages for known vulnerabilities and review dependency updates before changing versions.
  • Record tested Python and dependency versions to make installations reproducible.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • 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
Findings (11)

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · social_intel.py (reported line 580)May include surrounding context.

python
请用中文输出,简洁有条理,100字以内。"""

    return prompt  # 返回 prompt,供上层用 MiniMax LLM 处理


# ── 打印报告 ─────────────────────────────────────────────────────

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill advertises capabilities that imply shell execution, network access, and file writing, but it does not declare any explicit tool scope or permissions boundaries. In an agent environment, this increases the chance of over-privileged execution, unexpected external requests, and arbitrary writes without user-visible consent or policy enforcement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill openly supports scraping, comment collection, multi-platform retrieval, caching, and export, but provides no warning about privacy implications, platform terms, or that user queries and retrieved content may be transmitted over the network and stored locally. This can lead to collection or retention of personal data without informed consent and increases compliance, privacy, and data-handling risk.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The trigger phrases are broad enough to match many generic requests such as analysis, comparison, export, and trend tracking, which can cause the skill to activate outside its intended context. Overbroad activation is risky here because the skill can invoke scraping, shell commands, network access, and file output, expanding the blast radius of an accidental match.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script executes an external CLI tool (mcporter) and relies on local crawler integrations, but this behavior is not disclosed in the skill description. Hidden external integrations matter because user queries and identifiers are transmitted outside the script boundary, creating trust, privacy, and supply-chain risk.

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 · social_intel.py (reported line 75)May include surrounding context.

python
def run_cmd(cmd, timeout=25):
    try:
        r = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, shell=False)
        return r.stdout.strip()
    except Exception:
        return ""

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script sends search keywords and note/comment identifiers to external tooling without an explicit notice to the user. This creates a privacy and data-governance issue because operationally sensitive queries or identifiers may be exposed to third-party services or local integrations the user did not expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Search results are cached to /tmp without any clear user-facing notice, and the tool also supports collecting comments. Storing scraped social-media data on disk can expose potentially sensitive content to other local users, backups, or later processes, especially on shared systems.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The implemented --comments mode collects social-media comments, but the skill description does not disclose that capability. This can mislead users about the scope of data collection, especially because comments may contain personal data and create higher privacy/compliance exposure than simple post search.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The name, description, trigger phrases, and examples are all presented in Chinese, which implicitly constrains usage to a single language. There is no indication that users may interact in other languages or that the Chinese-only presentation is an intentional, justified locale limitation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The prompt explicitly instructs the model to respond in Chinese regardless of user preference or environment. This is a natural-language locale policy issue because the script does not offer any language selection or document a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.