Back to skill

Security audit

Tumblr Auto Post

Security checks for vulnerabilities and agentic risk

Overview

This skill should be reviewed carefully because it auto-publishes to a fixed Tumblr account using hard-coded OAuth credentials and lacks a real preview or confirmation boundary.

Do not install this as-is unless you control the Tumblr account and accept immediate public posting. The credentials should be revoked and removed from the package, replaced with user-provided secrets or OAuth, and the workflow should default to preview or draft with an explicit final publish confirmation.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/tumblr_post.py:20
Finding

Hard-Coded Tumblr OAuth Credentials Expose Account Access

Content
View full analysis

Vulnerability Details

File Location: scripts/tumblr_post.py:20-24; credentials are also disclosed in SKILL.md:20-22
Vulnerability Type: Hard-coded secrets and plaintext credential exposure
Risk Level: High

Evidence

scripts/tumblr_post.py:20-24:

python
CONSUMER_KEY = "6hFfvv3WkP46yy6Bgif9f8n0rOhli7eOTHOnBJ07PXk7njZrYK"
CONSUMER_SECRET = "wJniuQfcmUoDbzq87GNIV6eki4VJsdclU0d3q5k3TgYNZZQgeq"
ACCESS_TOKEN = "55OHtil3amJeXLDnTGknXgCGJD7SLM0f09LaS7c0fTkV7w7vAS"
ACCESS_TOKEN_SECRET = "WHzIBb01txQwvsbO0T5cD0W46EKkFgBNVXJkCXA9JTTq04554h"
BLOG_NAME = "remoneofcourse"

SKILL.md:20-22 additionally exposes credential material:

text
Tumblr account: remoneofcourse
Consumer Key: 6hFfvv3WkP46yy6Bgif9f8n0rOhli7eOTHOnBJ07PXk7njZrYK
Access Token: 55OHtil3amJeXLDnTGknXgCGJD7SLM0f09LaS7c0fTkV7w7vAS

Technical Analysis

The Skill embeds a complete Tumblr OAuth 1.0 credential set directly in distributed source code. The consumer secret and access-token secret are not configuration identifiers; they are authentication secrets that must remain confidential. Anyone with read access to the Skill package, a copied archive, build output, logs containing the source, or repository history can recover them without needing access to the original operator's environment.

The credentials are actively consumed by OAuth1Session in scripts/tumblr_post.py:111-114:

python
tumblr = OAuth1Session(
    CONSUMER_KEY, client_secret=CONSUMER_SECRET,
    resource_owner_key=ACCESS_TOKEN, resource_owner_secret=ACCESS_TOKEN_SECRET
)

The resulting authenticated session creates posts under the configured Tumblr blog. Moving the same strings into another script would allow an unauthorized party to construct equivalent signed requests, subject to the permissions and continued validity of the exposed token.

Because the credentials have been committed to plaintext, merely deleting them from the lates ...[truncated 1591 chars]

Remediation
View remediation

Remediation Suggestions

  1. Revoke and rotate immediately

    • Revoke the exposed Tumblr access token and access-token secret.
    • Rotate the consumer secret and consumer key where Tumblr supports doing so.
    • Treat all values shown in the package and documentation as compromised.
    • Review Tumblr account activity for unauthorized posts or API operations.
  2. Remove secrets from all tracked content

    • Delete credential values from scripts/tumblr_post.py and SKILL.md.
    • Purge them from repository history, release archives, caches, build artifacts, and published Skill packages.
    • Be aware that history rewriting does not invalidate previously copied credentials; rotation remains mandatory.
  3. Use protected runtime configuration

    • Read secrets from environment variables or an operating-system-backed secret manager.
    • Fail closed with a clear error when required variables are absent.
    • Do not print credentials or include them in exception messages.

    Example:

    python
    CONSUMER_KEY = os.environ["TUMBLR_CONSUMER_KEY"]
    CONSUMER_SECRET = os.environ["TUMBLR_CONSUMER_SECRET"]
    ACCESS_TOKEN = os.environ["TUMBLR_ACCESS_TOKEN"]
    ACCESS_TOKEN_SECRET = os.environ["TUMBLR_ACCESS_TOKEN_SECRET"]
    BLOG_NAME = os.environ["TUMBLR_BLOG_NAME"]
    
  4. Reduce credential privileges

    • Issue a dedicated token for this Skill.
    • Grant only the minimum publishing and read permissions required.
    • Avoid sharing tokens between production accounts, users, or unrelated automation.
  5. Prevent recurrence

    • Add secret scanning to pre-commit hooks and continuous integration.
    • Block commits matching OAuth tokens, API keys, and private-key patterns.
    • Provide placeholders such as TUMBLR_ACCESS_TOKEN in documentation rather than live values.
    • Establish scheduled credential rotation and audit logging for automated publishing.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented behavior materially misrepresents what the skill does: it claims a multi-step, confirmatory workflow but also enables direct posting using hardcoded credentials to a fixed external account. This is dangerous because users and reviewers may consent to a benign drafting flow while the skill actually performs sensitive, externally visible actions without meaningful approval.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Embedding account credentials in a natural-language configuration block discloses sensitive access data in a highly accessible form. Because the skill's purpose is direct Tumblr posting, the surrounding context makes these secrets immediately actionable for misuse against a real external account.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The documentation exposes live Tumblr credentials directly in the skill file, which can be copied and abused by anyone with access to the repository or package. Embedded secrets enable unauthorized posting, account takeover of the application's API context, and long-term compromise until the credentials are revoked.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
99% confidence
Finding

The exposed access token is a direct credential that can be used to authenticate to Tumblr on behalf of the associated account or application context. In this skill, the token is especially dangerous because it is paired with account information and an explicit posting workflow, lowering the barrier to immediate abuse.

Content

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

text
Tumblr 账号:remoneofcourse
Consumer Key:6hFfvv3WkP46yy6Bgif9f8n0rOhli7eOTHOnBJ07PXk7njZrYK
Access Token:55OHtil3amJeXLDnTGknXgCGJD7SLM0f09LaS7c0fTkV7w7vAS

完整对话流程(自动模式)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script embeds live Tumblr OAuth secrets directly in source code, exposing credentials to anyone who can read the skill. This enables unauthorized posting, account abuse, and persistent compromise of the linked Tumblr blog, especially dangerous because the skill automatically publishes content to a real account.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code silently uses hard-coded OAuth credentials without disclosing that it is operating under a preconfigured account. Users may believe they are generating draft content locally, while the script can authenticate and act on behalf of the embedded Tumblr account without meaningful transparency.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares shell-capable behavior but omits any explicit tool scope or permission boundary. In a skill that can publish externally and invoke local commands, this increases the risk of unexpected command execution and makes review and enforcement harder.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The natural-language description and interaction flow are entirely specified in Chinese, including the prompts the skill uses, with no indication that the user may choose another language. Under the policy, forcing a specific language without opt-in is a locale/language policy violation unless clearly justified as region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill advertises automatic public posting after answering questions, without a strong warning that publication is externally visible and potentially irreversible. In the context of social-media posting, missing consent and impact disclosure can cause accidental publication, reputational harm, and disclosure of sensitive or low-quality content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script invokes an external command through subprocess to run another skill's image-generation script, which is a code-execution boundary with potential side effects. While it prints that image generation is in progress, it does not clearly disclose in documentation or comments that running this script will execute another tool and may trigger additional downstream API usage or system activity.

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

python
print(f"  🎨 生成封面图中...")
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
        if result.returncode == 0:
            print(f"  ✅ 封面图已保存: {output_path}")
            return True

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill description says it auto-generates a 'Fu Sheng style' article after asking for audience, goals, length, and preferences, implying generation tailored to those inputs. The write_article function instead returns a mostly hard-coded essay template and varies only the topic and timestamp, so the implemented behavior is much narrower than described.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script performs authenticated network publication to Tumblr automatically, with no final confirmation step before transmitting content. In the context of a skill that claims to ask for confirmation before posting, this discrepancy increases the risk of unintended publication, privacy leakage, and misuse of the connected account.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This call transmits generated content and image data to Tumblr's external API. External transmission is expected for an auto-posting skill, but it becomes security-relevant here because it occurs using embedded credentials and without robust consent controls, creating risk of unintended disclosure and unauthorized account activity.

Content

Scanner excerpt · scripts/tumblr_post.py (reported line 110)May include surrounding context.

python
image_data = f.read()

            resp = tumblr.post(
                f"https://api.tumblr.com/v2/blog/{BLOG_NAME}.tumblr.com/post",
                data={"type": "photo", "caption": f"<h2>{sanitize_html(title)}</h2>{content}"},
                files={"data": ("image.jpg", image_data, "image/jpeg")}
            )

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This request sends the generated article body to Tumblr over the network for publication. While aligned with the skill's purpose, it is still a true security concern in context because the transmission is authenticated with embedded secrets and happens automatically, increasing the chance of unintended public posting.

Content

Scanner excerpt · scripts/tumblr_post.py (reported line 126)May include surrounding context.

python
# 纯文本发布
    resp = tumblr.post(
        f"https://api.tumblr.com/v2/blog/{BLOG_NAME}.tumblr.com/post",
        data={"type": "text", "title": title, "body": content}
    )

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/tumblr_post.py (reported line 134)May include surrounding context.

python
post_url, post_id = get_post_url(resp)
        # 通过最新一篇确认 URL
        get_resp = tumblr.get(
            f"https://api.tumblr.com/v2/blog/{BLOG_NAME}.tumblr.com/posts",
            params={"limit": 1, "type": "text"}
        )
        if get_resp.ok:

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest says each run will sequentially ask for topic, target audience, writing goal, desired length, and content preferences before confirming and auto-posting. In code, main() only reads one positional argument as the topic and otherwise falls back to a default, with no prompts, no collection of the other fields, and no confirmation step.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.