Back to skill

Security audit

Kiro Creator Monitor Daily Brief

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent daily monitoring helper that uses disclosed sources and optional user-enabled delivery, with some hardening gaps users should understand before enabling delivery or custom feeds.

Install only if you are comfortable with it making outbound requests to the configured public sources. Review RSS feed URLs before use, keep the config writable only by trusted users, and enable Telegram, Slack, or email delivery only when you are comfortable sending the full generated brief to those services using the supplied credentials.

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/daily_brief.py:122
Finding

Configurable RSS URLs Permit Server-Side Request Forgery

Content
View full analysis
str: req = urllib.request.Request(url, headers={"User-Agent": UA, **(headers or {})}) with urllib.request.urlopen(req, timeout=20) as resp: return resp.read().decode("utf-8", errors="replace") ``` ```python def fetch_rss(cfg: dict[str, Any]) -> list[Item]: if not cfg.get("enabled"): return [] per_feed = int(cfg.get("per_feed", 20)) out: list[Item] = [] for feed in cfg.get("feeds", []): try: xml = http_text(feed) except Exception: continue ``` ### Technical Analysis RSS feed URLs are read directly from the configuration and passed to `urllib.request.urlopen` without validating the URL scheme, hostname, resolved IP address, or redirect destination. Consequently, anyone able to modify the Skill configuration can make the process issue requests to destinations beyond legitimate public RSS feeds, including: - Loopback services such as `127.0.0.1` or `[::1]` - Private network services - Link-local addresses and cloud instance metadata endpoints - Internal services exposed only to the host running the Skill - Public endpoints that redirect to an internal destination The timeout limits request duration but does not restrict the destination. No response-size limit is applied either, allowing a configured server to return an excessively large response before XML parsing. If an internal response is valid RSS or Atom XML, its titles, links, and descriptions can enter `latest.json` and `latest.md`. When report delivery is enabled, selected response content may also be forwarded to Telegram, Slack, or email. ### Attack Path 1. An attacker gains the ability to supply or modify the JSON configuration used by `- ...[truncated 1256 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/daily_brief.py:311
Finding

SMTP STARTTLS Does Not Explicitly Enforce Certificate Verification

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (13)

Tainted flow: 'req' from os.getenv (line 301, 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/daily_brief.py (reported line 44)May include surrounding context.

python
def http_json(url: str, headers: dict[str, str] | None = None) -> dict[str, Any]:
    req = urllib.request.Request(url, headers={"User-Agent": UA, **(headers or {})})
    with urllib.request.urlopen(req, timeout=20) as resp:
        return json.loads(resp.read().decode("utf-8", errors="replace"))

Tainted flow: 'req' from os.getenv (line 301, 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/daily_brief.py (reported line 50)May include surrounding context.

python
def http_json(url: str, headers: dict[str, str] | None = None) -> dict[str, Any]:
    req = urllib.request.Request(url, headers={"User-Agent": UA, **(headers or {})})
    with urllib.request.urlopen(req, timeout=20) as resp:
        return json.loads(resp.read().decode("utf-8", errors="replace"))

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The Telegram delivery path sends the generated brief text to an external service using credentials from environment variables, which creates a real data-exfiltration channel when --deliver is used. In this skill context, the content may aggregate internal monitoring interests or sensitive summaries, and the code performs transmission with no content classification, confirmation, or destination validation beyond token/chat presence.

Content

Scanner excerpt · scripts/daily_brief.py (reported line 291)May include surrounding context.

python
payload = urllib.parse.urlencode({"chat_id": chat_id, "text": text, "disable_web_page_preview": "true"}).encode()
    req = urllib.request.Request(url, data=payload, headers={"User-Agent": UA})
    try:
        with urllib.request.urlopen(req, timeout=20):
            return None
    except Exception as e:
        return f"telegram error: {e}"

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

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The Slack delivery function posts the full generated brief to a webhook URL taken from the environment. Because webhook URLs are bearer secrets and may point to external or attacker-controlled Slack workspaces if misconfigured, this creates a real outbound exfiltration path for aggregated content with no verification, redaction, or user-facing warning in the send path.

Content

Scanner excerpt · scripts/daily_brief.py (reported line 307)May include surrounding context.

python
headers={"Content-Type": "application/json", "User-Agent": UA},
    )
    try:
        with urllib.request.urlopen(req, timeout=20):
            return None
    except Exception as e:
        return f"slack error: {e}"

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises capabilities that imply access to environment variables, filesystem read/write, and network communication, but it does not declare any explicit tool scope such as permissions or allowed-tools. That omission weakens transparency and reviewability, making it easier for a skill with external delivery features to access secrets or exfiltrate collected data without clear user awareness.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation describes optional Telegram, Slack, and email delivery, but it does not clearly warn that collected monitoring results will be transmitted to third-party external services. In a monitoring skill that aggregates potentially sensitive topics and drafts, this can lead to unintended data disclosure if users enable delivery without understanding the outbound sharing behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The X query string includes lang:en, which forces English-only retrieval. For a config file, this is a natural-language locale policy concern because the file does not offer a language choice or explain why English-only filtering is required.

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

python
"tweet.fields": "created_at,public_metrics,lang",
            "expansions": "author_id",
        }
        url = f"https://api.x.com/2/tweets/search/recent?{urllib.parse.urlencode(params)}"
        try:
            data = http_json(url, headers=headers)
        except Exception:

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

python
per_repo = int(cfg.get("per_repo", 10))
    out: list[Item] = []
    for repo in cfg.get("repos", []):
        url = f"https://api.github.com/repos/{repo}/releases?per_page={max(1, min(per_repo, 100))}"
        try:
            data = http_json(url)
        except Exception:

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This code constructs a Telegram API URL with a bot token embedded in the path and transmits the generated brief externally. Although such use is standard for Telegram bots, in this skill it is a meaningful external-transmission sink because it can export aggregated monitoring output off-system, and the token-bearing destination is sensitive if mishandled or logged elsewhere.

Content

Scanner excerpt · scripts/daily_brief.py (reported line 287)May include surrounding context.

python
chat_id = os.getenv("TELEGRAM_CHAT_ID", "").strip()
    if not token or not chat_id:
        return "telegram skipped: TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID missing"
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    payload = urllib.parse.urlencode({"chat_id": chat_id, "text": text, "disable_web_page_preview": "true"}).encode()
    req = urllib.request.Request(url, data=payload, headers={"User-Agent": UA})
    try:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

When --deliver is supplied, the code automatically sends the compiled markdown brief to any enabled external channels without an interactive warning, review step, or content sensitivity check. In a monitoring skill, that is materially risky because the output aggregates multiple sources and may include sensitive operational interests, drafts, or data the operator did not intend to export.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The schedule instructions specify using timezone America/New_York, which imposes a locale-specific setting in natural-language guidance. The file does not indicate that this timezone is only an example or that users may choose a different timezone, so it can be read as forcing a specific locale without opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code creates the output directory and writes both config.json and .env.template into it, but provides no prior confirmation prompt, warning comment, or user-facing disclosure before performing these file writes. Because file creation/modification is a safety-relevant operation under the rule, the lack of any visible warning in this code file is a reportable omission.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.