Back to skill

Security audit

get-tldr

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says by calling get-tldr.com, but it also stores submitted URLs and full responses locally and requires untrusted remote Markdown to be shown without filtering.

Review this skill before installing. Use it only with public, non-sensitive URLs that do not contain tokens or private query parameters. Be aware that it sends URLs to get-tldr.com and, by default, keeps a local log of both the URL and the full returned summary. Treat the displayed summary as untrusted third-party content, especially when it contains Markdown links or instruction-like text.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
get_tldr.py:91
Finding

Plaintext Logging of Sensitive URLs and API Responses

Content
View full analysis

Vulnerability Details

File Location: get_tldr.py:91-103
Vulnerability Type: Sensitive information stored in plaintext
Risk Level: Medium

Vulnerable Code

python
result = summarize(url)
# append a log entry: timestamp, sent payload and response payload (ignore errors)
try:
    sent_payload = {"input": url}
    with open(LOGFILE, "a", encoding="utf-8") as lf:
        lf.write(json.dumps({
            "timestamp": datetime.utcnow().isoformat() + "Z",
            "sent": sent_payload,
            "response": result
        }, ensure_ascii=False) + "\n")
except Exception:
    pass
print(json.dumps(result, ensure_ascii=False, indent=2))

Technical Analysis

The script persistently records every submitted URL and the complete response from the summarization API. By default, these records are written to ~/.config/get-tldr/skill.log. URLs can contain sensitive query parameters, signed access tokens, private document identifiers, session information, or personal data. API responses may also include confidential content extracted from the submitted resource.

The log is opened using the process's default file-creation permissions rather than an explicitly restrictive mode. Its effective permissions consequently depend on the parent directory and the user's umask. No redaction, retention limit, rotation, encryption, or explicit user consent is implemented. Logging exceptions are also suppressed, preventing users from knowing whether and where sensitive information was stored.

Attack Path

  1. A user invokes the skill with a private or tokenized URL.
  2. The script sends the URL to the declared external summarization service.
  3. The script writes both the complete URL and API response to the configured or default log file.
  4. A local process, another user with filesystem access, a backup system, or an overly broad logfile destination reads the retained record.
  5. The exposed URL t ...[truncated 616 chars]
Remediation
View remediation

Remediation Suggestions

  • Disable request and response logging by default and require explicit user opt-in.
  • Do not log complete URLs. Remove query strings and fragments or redact known secret-bearing parameters such as token, key, signature, and auth.
  • Avoid logging API response bodies unless necessary for explicitly enabled debugging.
  • Create the logfile with mode 0600 and verify that the parent directory is accessible only to the current user.
  • Reject logfile paths that resolve to unsafe or unexpectedly shared locations, or clearly document the trust boundary when custom paths are allowed.
  • Add bounded retention, secure rotation, and deletion controls.
  • Notify users when logging is active and report logging failures without exposing secrets.
  • Review existing logfiles and securely delete records that are no longer required.

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:13
Finding

Mandatory Verbatim Rendering of Untrusted Remote Content

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:13-14
Vulnerability Type: Untrusted content and instruction pass-through
Risk Level: Medium

Vulnerable Instructions

markdown
- IMPORTANT: The API response is already a summary; the skill must NOT further summarize or alter the content — only take the value of the "summary" element of the json and format it for readability. Take the entire summary property, do not omit anything.
- IMPORTANT: If the summary element of the response json from the API already is formatted in markdown, just return the formatted markdown. Do not omit anything and do not change the text. Make sure its not wrapped in a code block and if so remove the wrapping code block, so that it correctly renders as markdown, but not as a code block.

Technical Analysis

The skill requires the agent to reproduce the external API's summary field without alteration or omission and to render any returned Markdown directly. That response is derived from an arbitrary user-selected webpage and generated by a third-party service, so it must be treated as untrusted content.

A malicious webpage can contain prompt-like instructions, deceptive links, misleading claims, or Markdown intended to appear as authoritative assistant output. The prohibition against omission or modification prevents the agent from removing unsafe content. Removing a wrapping code block further changes potentially inert text into rendered Markdown.

The reviewed code does not execute the returned content as local code and does not independently grant it tool access. The primary risk is content and instruction injection into the current interaction rather than operating-system compromise.

Attack Path

  1. An attacker creates or modifies a webpage to include adversarial instructions, deceptive Markdown, or malicious links.
  2. A victim asks the skill to summarize that webpage.
  3. The external service incorporates attacker-co ...[truncated 859 chars]
Remediation
View remediation

Remediation Suggestions

  • Explicitly classify the API response as untrusted data rather than agent instructions.
  • Present remote summaries inside a clearly labeled quotation or other content boundary.
  • Permit the agent to omit or neutralize prompt-like instructions, deceptive links, active content, and other unsafe material.
  • Do not require automatic removal of code-block boundaries when doing so would cause untrusted Markdown to render actively.
  • Ensure returned text cannot authorize tool calls, modify system behavior, override higher-priority instructions, or request sensitive information.
  • Preserve factual summary content where safe, but add a visible warning when material has been filtered or escaped for security.
  • Consider rendering untrusted output as plain text or sanitized Markdown with links disabled or visibly annotated.
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (17)

Tainted flow: 'headers' from os.environ.get (line 67, credential/environment) → requests.post (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 · get_tldr.py (reported line 68)May include surrounding context.

python
def summarize(url: str):
    payload = {"input": url}
    headers = {"Content-Type": "application/json", "X-API-Key": API_KEY}
    resp = requests.post(API_URL, headers=headers, json=payload, timeout=30)
    try:
        resp.raise_for_status()
        return resp.json()

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description says the skill only returns the API summary as-is, but the documented behavior also reads secrets from local config/.env and writes request/response data to a logfile. This mismatch is dangerous because users may invoke the skill expecting simple formatting while it silently accesses local credentials and persists potentially sensitive content to disk.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

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

md
Call get-tldr.com summarize API with a single URL argument.
Usage: python3 get_tldr.py "https://example.com/..."
Prints the JSON response to stdout.
Reads api_token and optional logfile from ~/.config/get-tldr/config.json (preferred), falling back to GET_TLDR_API_KEY or a .env file in the skill folder. If no logfile is configured the script defaults to ~/.config/get-tldr/skill.log.
This script is used by the get-tldr skill.
"""
import sys

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

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

md
Call get-tldr.com summarize API with a single URL argument.
Usage: python3 get_tldr.py "https://example.com/..."
Prints the JSON response to stdout.
Reads api_token and optional logfile from ~/.config/get-tldr/config.json (preferred), falling back to GET_TLDR_API_KEY or a .env file in the skill folder. If no logfile is configured the script defaults to ~/.config/get-tldr/skill.log.
This script is used by the get-tldr skill.
"""
import sys

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · get_tldr.py (reported line 6)May include surrounding context.

python
Call get-tldr.com summarize API with a single URL argument.
Usage: python3 get_tldr.py "https://example.com/..."
Prints the JSON response to stdout.
Reads api_token and optional logfile from ~/.config/get-tldr/config.json (preferred), falling back to GET_TLDR_API_KEY or a .env file in the skill folder. If no logfile is configured the script defaults to ~/.config/get-tldr/skill.log.
This script is used by the get-tldr skill.
"""
import sys

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · get_tldr.py (reported line 23)May include surrounding context.

python
Call get-tldr.com summarize API with a single URL argument.
Usage: python3 get_tldr.py "https://example.com/..."
Prints the JSON response to stdout.
Reads api_token and optional logfile from ~/.config/get-tldr/config.json (preferred), falling back to GET_TLDR_API_KEY or a .env file in the skill folder. If no logfile is configured the script defaults to ~/.config/get-tldr/skill.log.
This script is used by the get-tldr skill.
"""
import sys

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · get_tldr.py (reported line 44)May include surrounding context.

python
Call get-tldr.com summarize API with a single URL argument.
Usage: python3 get_tldr.py "https://example.com/..."
Prints the JSON response to stdout.
Reads api_token and optional logfile from ~/.config/get-tldr/config.json (preferred), falling back to GET_TLDR_API_KEY or a .env file in the skill folder. If no logfile is configured the script defaults to ~/.config/get-tldr/skill.log.
This script is used by the get-tldr skill.
"""
import sys

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · get_tldr.py (reported line 46)May include surrounding context.

python
# fallback to .env file located in the same folder as this script
if not API_KEY:
    env_path = os.path.join(os.path.dirname(__file__), ".env")
    try:
        with open(env_path, "r", encoding="utf-8") as f:
            for line in f:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares no explicit tool scope even though it requires network access, reads local files and environment variables for secrets, and writes logs to disk. Without a permissions/allowed-tools declaration, an agent or reviewer cannot easily constrain or audit what the skill is allowed to access, increasing the chance of unintended secret access, file writes, or external data transmission.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill does not clearly warn users that any provided URL is sent to a third-party service for processing. In context, this is especially risky because URLs may contain sensitive query strings, internal endpoints, private document locations, or access tokens that would then be disclosed externally.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The skill instructs maintainers to create persistent config and log files under ~/.config, and the script defaults to writing logs there. Persistent storage of API configuration and possibly request/response data can leave sensitive artifacts on disk across sessions, creating privacy and forensic exposure beyond the user’s expectation for a simple summarization skill.

Content

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

  • get_tldr.py — small Python script (located in the skill folder) that posts {"input": ""} to https://www.get-tldr.com/api/v1/summarize using the required X-API-Key header and prints the JSON response to stdout. The script reads the API key and an optional logfile path from ~/.config/get-tldr/config.json (preferred), or falls back to the GET_TLDR_API_KEY environment variable or a .env file in the skill folder. If no logfile is configured the script defaults to ~/.config/get-tldr/skill.log.

Notes for maintainers:

  • Create the config file at ~/.config/get-tldr/config.json with the following structure (JSON):
text
{

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · get_tldr.py (reported line 61)May include surrounding context.

python
pass

if not API_KEY:
    print(json.dumps({"error": "Missing API key. Create ~/.config/get-tldr/config.json with api_token, or set GET_TLDR_API_KEY env var or place it in this skill folder's .env."}))
    sys.exit(1)

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · get_tldr.py (reported line 68)May include surrounding context.

python
def summarize(url: str):
    payload = {"input": url}
    headers = {"Content-Type": "application/json", "X-API-Key": API_KEY}
    resp = requests.post(API_URL, headers=headers, json=payload, timeout=30)
    try:
        resp.raise_for_status()
        return resp.json()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script transmits the provided URL to an external service without an execution-time warning or consent prompt. If users pass internal, private, or tokenized URLs, this may disclose sensitive information to a third party beyond what the skill description makes obvious.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script logs the submitted URL and full API response to a local file even though the skill description says it should only return and format the API output. URLs and summaries may contain sensitive internal links, query tokens, or confidential content, creating unintended data retention on disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script silently persists both the requested URL and the API response to a local logfile. This creates a privacy and data-retention risk because users are not warned at runtime that potentially sensitive inputs and outputs are being stored.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The manifest describes a simple wrapper that returns the get-tldr summarize API output. While using an API key is expected, scanning both process environment variables and a colocated .env file adds credential-access behavior beyond the narrowly described scope and is not disclosed in the manifest description.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.