Back to skill

Security audit

Cross-Post

Security checks for vulnerabilities and agentic risk

Overview

This skill is a legitimate social-posting helper, but it can publish content to public accounts with weak safeguards and some behavior does not match its description.

Review carefully before installing. Use it only when you intend immediate public posting, run preview first, provide narrowly scoped social API credentials, avoid entering secrets in recorded or shared terminals, and treat the all-platform and scheduling claims as unreliable in this version.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cross_post.py:41
Finding

API credentials are collected through visible terminal input

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cross_post.py:24
Finding

Credential file is secured only after plaintext secrets are written

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (24)

Tainted flow: 'req' from os.environ.get (line 187, 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 · scripts/cross_post.py (reported line 83)May include surrounding context.

python
"https://api.twitter.com/2/users/me",
                headers=headers,
            )
            resp = urllib.request.urlopen(req, timeout=10)
            data = json.loads(resp.read())
            user_id = data["data"]["id"]
            config["twitter_user_id"] = user_id

Tainted flow: 'req' from os.environ.get (line 187, 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 · scripts/cross_post.py (reported line 113)May include surrounding context.

python
"https://api.twitter.com/2/users/me",
                headers=headers,
            )
            resp = urllib.request.urlopen(req, timeout=10)
            data = json.loads(resp.read())
            user_id = data["data"]["id"]
            config["twitter_user_id"] = user_id

Tainted flow: 'req' from os.environ.get (line 187, 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 · scripts/cross_post.py (reported line 130)May include surrounding context.

python
"https://api.twitter.com/2/users/me",
                headers=headers,
            )
            resp = urllib.request.urlopen(req, timeout=10)
            data = json.loads(resp.read())
            user_id = data["data"]["id"]
            config["twitter_user_id"] = user_id

Tainted flow: 'req' from os.environ.get (line 187, 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 · scripts/cross_post.py (reported line 196)May include surrounding context.

python
"https://api.twitter.com/2/users/me",
                headers=headers,
            )
            resp = urllib.request.urlopen(req, timeout=10)
            data = json.loads(resp.read())
            user_id = data["data"]["id"]
            config["twitter_user_id"] = user_id

Tainted flow: 'req' from os.environ.get (line 187, 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 · scripts/cross_post.py (reported line 232)May include surrounding context.

python
"https://api.twitter.com/2/users/me",
                headers=headers,
            )
            resp = urllib.request.urlopen(req, timeout=10)
            data = json.loads(resp.read())
            user_id = data["data"]["id"]
            config["twitter_user_id"] = user_id

Tainted flow: 'req' from os.environ.get (line 187, 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 · scripts/cross_post.py (reported line 286)May include surrounding context.

python
"https://api.twitter.com/2/users/me",
                headers=headers,
            )
            resp = urllib.request.urlopen(req, timeout=10)
            data = json.loads(resp.read())
            user_id = data["data"]["id"]
            config["twitter_user_id"] = user_id

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description mostly matches the general domain and intent: the script is clearly for social posting to Twitter/X, Reddit, and LinkedIn, and it includes Reddit title/subreddit handling plus Twitter thread support. However, there are material mismatches. First, the headline capability of cross-posting to multiple platforms from one prompt is not functioning as described: when --platform all is selected, the code sets platforms = ['all'] and then never dispatches to twitter/reddit/linkedin, so no posts occur. Second, the description explicitly claims scheduling social posts, but there is no scheduling logic, delayed execution, queueing, or time-based posting. Third, the claimed professional formatting for LinkedIn is not really implemented; format_platforms() is a no-op and is never used. These are material description-to-behavior mismatches, even though the core social-posting purpose is aligned.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
# LinkedIn
    print("\nLinkedIn (optional):")
    config["linkedin_access_token"] = input("  Access Token (leave blank to skip): ").strip()
    config["linkedin_person_urn"] = input("  Person URN: ").strip()

    write_config(config)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/cross_post.py (reported line 56)May include surrounding context.

python
# LinkedIn
    print("\nLinkedIn (optional):")
    config["linkedin_access_token"] = input("  Access Token (leave blank to skip): ").strip()
    config["linkedin_person_urn"] = input("  Person URN: ").strip()

    write_config(config)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/cross_post.py (reported line 249)May include surrounding context.

python
"""Post to LinkedIn."""
    token = config.get("linkedin_access_token", "")
    if not token:
        print("[LinkedIn] SKIPPED: No access token configured")
        return

    headers = {

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

LinkedIn posts are hardcoded to PUBLIC visibility and are published immediately without warning or confirmation. In an agent setting, this is especially risky because a mistaken prompt or inclusion of internal information could cause instant public disclosure under the user's professional identity, creating reputational and confidentiality impact.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill invokes a Python script with access to filesystem, environment variables, network, and shell execution but does not declare any tool scope or permission boundaries in the manifest. In an agent setting, that omission weakens reviewability and can lead to overbroad execution of sensitive actions such as reading credentials and posting externally without explicit constraint.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest uses broad trigger phrases like 'post this' or 'share on twitter/reddit/linkedin,' which can cause the skill to activate on common user requests without sufficient precision. In a skill that performs external posting, over-triggering increases the risk of unintended publication of sensitive, draft, or private content to third-party platforms.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill description does not clearly warn that using it transmits user content to external social-media services. In this context, omission of that warning is risky because users may provide sensitive or unpublished text expecting local assistance, not immediate distribution to Twitter/X, Reddit, and LinkedIn.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
## Security

Config file is chmod 600. Never commit config.json.

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 · scripts/cross_post.py (reported line 80)May include surrounding context.

python
if not user_id:
        try:
            req = urllib.request.Request(
                "https://api.twitter.com/2/users/me",
                headers=headers,
            )
            resp = urllib.request.urlopen(req, timeout=10)

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 · scripts/cross_post.py (reported line 108)May include surrounding context.

python
if not user_id:
        try:
            req = urllib.request.Request(
                "https://api.twitter.com/2/users/me",
                headers=headers,
            )
            resp = urllib.request.urlopen(req, timeout=10)

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 · scripts/cross_post.py (reported line 125)May include surrounding context.

python
if not user_id:
        try:
            req = urllib.request.Request(
                "https://api.twitter.com/2/users/me",
                headers=headers,
            )
            resp = urllib.request.urlopen(req, timeout=10)

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/cross_post.py (reported line 179)May include surrounding context.

python
auth = urllib.request.HTTPBasicAuthHandler()
    credentials = f"{client_id}:{client_secret}"
    encoded = credentials.encode()
    encoded_b64 = __import__("base64").b64encode(encoded).decode()

    data = urllib.parse.urlencode({
        "grant_type": "password",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The tool submits Reddit posts immediately without a confirmation step, despite transmitting potentially sensitive or unintended user-provided content to an external public platform. In an agent skill context, where generated text may include confidential data or be triggered with ambiguous user intent, one-step live posting materially increases the chance of accidental disclosure.

Content

No source excerpt is available for this finding.

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 · scripts/cross_post.py (reported line 281)May include surrounding context.

python
try:
        req = urllib.request.Request(
            "https://api.linkedin.com/v2/ugcPosts",
            data=json.dumps(payload).encode(),
            headers=headers,
            method="POST",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The main post command performs live external publication with no overall confirmation barrier, increasing the risk of accidental or prompt-induced posting. Because this skill is designed for cross-platform publication, a single mistaken invocation can amplify unintended disclosure across multiple social accounts.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The default 'all' option is broken because the code sets platforms = ['all'] and then never maps that value to twitter, reddit, and linkedin, so nothing is posted while still printing 'Done!'. In a publishing tool, this mismatch between claimed and actual behavior is dangerous because users may rely on false assumptions about what was published, potentially causing missed disclosures, inconsistent communications, or accidental retries to the wrong platforms.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest says the skill can be used to schedule social posts, but the CLI only supports immediate post, preview, and init-config actions. There is no code for delayed execution, storing scheduled jobs, or accepting a schedule time parameter, so the implementation does not match the described scope.

Content

No source excerpt is available for this finding.