Back to skill

Security audit

Newsletter Launch

Security checks for vulnerabilities and agentic risk

Overview

This newsletter automation skill is purpose-aligned overall, but it exposes Beehiiv API keys by storing, printing, scheduling, and committing them in plaintext.

Review carefully before installing. Do not provide a real Beehiiv API key unless the skill is changed to use a secret store or environment variable, avoids printing tokens, and never commits config files containing secrets. Treat auto-publishing as live public posting authority and enable it only with a least-privilege key and clear approval controls.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/scaffold_newsletter.py:249
Finding

Beehiiv API credentials are stored in plaintext and staged in Git

Content
View full analysis
/` according to `SKILL.md`. Because the complete project directory is staged, that additional copy of the credential may also be committed. This violates least-exposure principles for authentication material. Git is particularly unsuitable for secret storage because deleting the working-tree file later does not remove the credential from commit history, clones, m ...[truncated 1458 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/build_crons.py:62
Finding

API key is embedded in persistent cron payloads and emitted to standard output

Content
View full analysis
", "subtitle": "", "content_html": "", "slug": "", "meta_default_title": "", "meta_default_description": "", "audience": "both", "status": "confirmed", "schedule_for": "" }} Run: curl -s -X POST "https://api.beehiiv.com/v2/publications/{pub_id}/posts" \\ -H "Authorization: Bearer {api_key}" \\ -H "Content-Type: application/json" \\ -d '' If successful: log post ID to issue-log.md, update status to 'published'. If failed: alert {owner} with full error and fallback to paste doc.""" ``` The key is also placed in the weekly cron and its dynamically created publish-check job: ```python KPI PULL: Fetch latest Beehiiv stats (subscriber count, last post open/click rate). Run: curl -s "https://api.beehiiv.com/v2/publications/{pub_id}/subscriptions?limit=1&status=active" -H "Authorization: Bearer {api_key}" Append a KPI row to the KPIs table in {project_file}. SPAWN PUBLISH-CHECK: Create a one-shot cron job (kind: at, {publish_day} noon {tz}) with this payload: "Check whether {name} Issue #[N] has been published to Beehiiv. Run: curl -s 'https://api.beehiiv.com/v2/publications/{pub_id}/posts?limit=5&status=confirmed' -H 'Authorization: Bearer {api_key}' If issue N found: update {issue_log} status to published. If not found: alert {owner}: '{name} Issue #[N] not published ye ...[truncated 2376 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/build_crons.py:70
Finding

Shell command construction with unescaped generated content permits command injection

Content
View full analysis
", "subtitle": "", "content_html": "", "slug": "", "meta_default_title": "", "meta_default_description": "", "audience": "both", "status": "confirmed", "schedule_for": "" }} Run: curl -s -X POST "https://api.beehiiv.com/v2/publications/{pub_id}/posts" \\ -H "Authorization: Bearer {api_key}" \\ -H "Content-Type: application/json" \\ -d '' If successful: log post ID to issue-log.md, update status to 'published'. If failed: alert {owner} with full error and fallback to paste doc.""" ``` ### Technical Analysis The cron instructs an Agent to build a JSON payload containing generated newsletter HTML and insert it into a shell command as: ```sh -d '' ``` Single quotes are not escaped or otherwise handled. Ordinary article text containing an apostrophe can prematurely terminate the shell string. More importantly, crafted content can close the quoted argument and append shell syntax. The payload includes dynamic values such as the title, subtitle, metadata, slug, and complete generated article. Those values can be influenced by newsletter configuration, researched web material, source documents, and generated content. Treating this material as executable shell text creates a data-to-code boundary violation. No direct `subprocess(..., shell=True)` call appears in the Python script. The exploitation boundary arises because the persistent Agent cron ...[truncated 1670 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (25)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description presents a full newsletter-launching skill that can set up a new newsletter end-to-end in one conversation, including scaffolding files and wiring automation. This code chunk is much narrower: it builds cron configuration objects for research, writing, evergreen posts, and quarterly keyword research, then outputs them as JSON. The script explicitly says another agent would read this output and call the cron API, so it does not itself 'wire up' crons. It also references expected existing files such as project markdown, issue templates, logs, and SEO briefs, indicating it is not creating the full project from scratch. While the cron-generation behavior is related to newsletter setup, the declared purpose materially overstates the implemented functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The script clearly supports part of the declared purpose: scaffolding files for a new newsletter project. However, several key claims in the description are not reflected in the code. There is no interactive setup wizard; the script expects an existing config JSON file as input. There is no code to configure or wire automation crons, despite the description presenting that as part of the launcher’s core function. It also does not check whether the newsletter-seo-pipeline skill is installed; it only writes references to that skill into generated files. Additionally, the code performs a git commit of the generated files, which is a real side effect not mentioned in the declared permissions or description. Because these omissions and extra behavior affect the primary capabilities users would expect, this is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill not only requests Beehiiv credentials in conversation, it instructs persistence of configuration in project files, creating a durable secret exposure path. Storing API credentials in plaintext project config makes them vulnerable to accidental commits, local disclosure, reuse by other tools, and leakage through backups or shared workspaces.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
- If output is `python3: can't open file` or `No such file or directory`: the script path is wrong — check that newsletter-seo-pipeline installed correctly with `ls <skill_dir>/scripts/`
- If `python3` itself errors: Python 3 is not installed or not on PATH

Clean up: `rm -f /tmp/nsp-test.md`

### Step 6: Confirm to user

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The auto-post logic embeds instructions for autonomous Beehiiv publishing using API credentials, allowing the generated cron workflow to publish content externally without a fresh user approval at publication time. In the context of a launcher skill, this is especially risky because it transforms setup into delegated publishing authority, which can cause unauthorized or erroneous public posts.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill invokes shell commands and writes files but declares no explicit tool scope or allowed-tools boundary. That increases the blast radius if the skill is triggered unexpectedly or modified later, because the agent may execute filesystem and shell actions without least-privilege constraints.

Content

No source excerpt is available for this finding.

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 · SKILL.md (reported line 10)May include surrounding context.

md
Use when starting a new newsletter from scratch or setting up a second
  newsletter on a new topic.
  Triggers on: 'launch a newsletter', 'new newsletter', 'start a newsletter',
  'set up a newsletter', 'create a newsletter', 'second newsletter',
  'newsletter on [topic]'.
  NOT for: editing an existing newsletter, writing issues, or keyword research.
  Requires: newsletter-seo-pipeline skill must be installed.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest excludes 'editing an existing newsletter' from the skill's scope, yet the 'Resuming an Existing Newsletter' section instructs the agent to load an existing config and perform 'update config, re-scaffold, add crons'. That is a direct expansion beyond the stated purpose of only launching a new newsletter.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill asks users to paste a Beehiiv API key directly into the conversation without warning about secret handling, transcript retention, or safer entry methods. In a chat-based system, secrets shared in plain conversation may be logged, surfaced to other tools, or later exposed through summaries or config files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill enables automatic publishing with API write access but does not present a clear risk warning or require a distinct informed-consent step. That can lead users to grant broad write privileges without understanding that the automation may publish directly to a live publication.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide tells users to generate and copy an API key but does not state that the key is a sensitive secret that must not be pasted into chats, committed to files, or shared broadly. In a skill that scaffolds and automates a newsletter workflow, this omission increases the chance the credential will be exposed to the agent, logs, or project artifacts, which could enable unauthorized access to the Beehiiv publication API.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The schema explicitly instructs the agent to write a JSON file containing a Beehiiv API key and Telegram user ID, but provides no guidance on secure handling, storage, redaction, or lifecycle management of that sensitive data. In a skill that scaffolds files and wires up automation, this increases the chance secrets are written to disk, committed, logged, or exposed to other tools and prompts, enabling account compromise or privacy leakage.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script generates four recurring cron jobs that continuously perform research, writing, SEO processing, KPI collection, publication checks, and optional auto-posting, which exceeds the stated purpose of a short setup wizard. This scope mismatch is dangerous because users invoking a launcher may not realize they are authorizing long-lived autonomous content production and operational activity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The generated cron instructions interpolate Beehiiv API credentials directly into message text and instruct downstream execution of external HTTP requests, but this file does not present clear user-facing disclosure or guardrails around those side effects. Embedding secrets in generated payloads increases the risk of credential exposure through logs, cron inspection, debugging output, or later prompt/file leakage.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The presence of the Beehiiv API endpoint confirms outbound network transmission to a third-party service as part of the generated automation. While not inherently malicious, it materially increases risk in a setup skill because it creates automatic data egress and publication capability beyond simple local scaffolding.

Content

Scanner excerpt · scripts/build_crons.py (reported line 86)May include surrounding context.

python
"schedule_for": "<publish date ISO8601>"
}}
Run:
curl -s -X POST "https://api.beehiiv.com/v2/publications/{pub_id}/posts" \\
  -H "Authorization: Bearer {api_key}" \\
  -H "Content-Type: application/json" \\
  -d '<payload>'

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The presence of the Beehiiv API endpoint confirms outbound network transmission to a third-party service as part of the generated automation. While not inherently malicious, it materially increases risk in a setup skill because it creates automatic data egress and publication capability beyond simple local scaffolding.

Content

Scanner excerpt · scripts/build_crons.py (reported line 86)May include surrounding context.

python
"schedule_for": "<publish date ISO8601>"
}}
Run:
curl -s -X POST "https://api.beehiiv.com/v2/publications/{pub_id}/posts" \\
  -H "Authorization: Bearer {api_key}" \\
  -H "Content-Type: application/json" \\
  -d '<payload>'

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The write cron includes KPI retrieval from Beehiiv and appends analytics data into project files, which is outside the launcher’s advertised setup scope. This creates an undisclosed data collection capability and expands the blast radius of the automation beyond scaffolding into ongoing analytics handling.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This external API call retrieves subscription-related Beehiiv data for KPI logging, causing ongoing transmission of authenticated requests to a third party. In context, this is more dangerous because analytics collection is not central to a launcher’s setup function and may surprise users who only intended to scaffold a newsletter.

Content

Scanner excerpt · scripts/build_crons.py (reported line 170)May include surrounding context.

python
Update {issue_log}: add row for issue N, status: draft.

KPI PULL: Fetch latest Beehiiv stats (subscriber count, last post open/click rate).
Run: curl -s "https://api.beehiiv.com/v2/publications/{pub_id}/subscriptions?limit=1&status=active" -H "Authorization: Bearer {api_key}"
Append a KPI row to the KPIs table in {project_file}.

SPAWN PUBLISH-CHECK: Create a one-shot cron job (kind: at, {publish_day} noon {tz}) with this payload:

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This call checks Beehiiv post status via an authenticated external request as part of a dynamically spawned cron. The danger comes from combining hidden autonomous scheduling with third-party access, which can create persistent background behavior and additional opportunities for credential leakage or unintended automation.

Content

Scanner excerpt · scripts/build_crons.py (reported line 175)May include surrounding context.

python
SPAWN PUBLISH-CHECK: Create a one-shot cron job (kind: at, {publish_day} noon {tz}) with this payload:
"Check whether {name} Issue #[N] has been published to Beehiiv.
Run: curl -s 'https://api.beehiiv.com/v2/publications/{pub_id}/posts?limit=5&status=confirmed' -H 'Authorization: Bearer {api_key}'
If issue N found: update {issue_log} status to published.
If not found: alert {owner}: '{name} Issue #[N] not published yet — paste doc at projects/{slug}/issue-[N]-FINAL-PASTE.md'
sessionTarget: main, deleteAfterRun: true."

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

python
def git_commit(workspace, slug, name):
    """Commit all new project files to git."""
    try:
        result = subprocess.run(
            ["git", "rev-parse", "--is-inside-work-tree"],
            cwd=str(workspace), capture_output=True, text=True
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
87% confidence
Finding

Although subprocess.run is used safely without shell=True, the script uses attacker-controlled slug data to construct git pathspecs. A slug beginning with '-' can be interpreted by git add as an option rather than a path, enabling argument injection into git and potentially altering what files are staged or how git behaves in the target workspace.

Content

Scanner excerpt · scripts/scaffold_newsletter.py (reported line 282)May include surrounding context.

python
if result.returncode != 0:
            return None, "workspace is not a git repo — skipping commit"

        subprocess.run(
            ["git", "add", f"projects/{slug}/", f"skills/newsletter-launch/.skill-config/{slug}.json"],
            cwd=str(workspace), check=True, capture_output=True
        )

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

python
["git", "add", f"projects/{slug}/", f"skills/newsletter-launch/.skill-config/{slug}.json"],
            cwd=str(workspace), check=True, capture_output=True
        )
        commit_result = subprocess.run(
            ["git", "commit", "-m", f"feat: launch newsletter '{name}' — scaffold project files and config"],
            cwd=str(workspace), capture_output=True, text=True
        )

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

Line L022 instructs checking for 'these 7 skill folders', but the dependency table lists entries 1 through 6 and L033 refers to 'all 6'. This is an internal documentation contradiction that can mislead the agent about required dependencies.

Content

No source excerpt is available for this finding.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

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

md
On first run (no config file at `skills/newsletter-launch/.skill-config/<slug>.json`):

Tell the user: *"I'll ask you 11 quick questions — takes about 2 minutes. I'll handle everything after that: project files, writing style guide, automation, crons. Let's go."*

Ask these questions **one at a time**, in order. Do not batch them.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The write-cron payload performs substantial side effects, including file writes, issue-log updates, KPI retrieval, and creation of a follow-on publish-check cron, without clearly documenting those behaviors in the script’s high-level interface. Hidden or under-disclosed side effects are risky in agent skills because users may authorize setup while unintentionally granting broader ongoing modification and automation privileges.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.