T09 · Insecure Skill Coding Practices
- Location
scripts/send_to_kindle.py:7- Finding
Hard-Coded Kindle Recipient Can Cause Unauthorized Document Disclosure
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its blog-to-Kindle purpose, but it has unsafe defaults and implementation flaws that can send documents or credentials to unexpected external destinations.
Review before installing. Remove the hard-coded Kindle address, require an explicit recipient and confirmation before sending, fix AppleScript argument handling, document one trusted cover-generation endpoint, and add URL, redirect, file-size, and content-type limits before using this with sensitive documents or real API credentials.
scripts/send_to_kindle.py:7Hard-Coded Kindle Recipient Can Cause Unauthorized Document Disclosure
scripts/send_to_kindle.py:10AppleScript Injection Through Unescaped Delivery Arguments
scripts/fetch_blog.py:40Unrestricted Custom Blog Fetching Permits Server-Side Request Forgery
scripts/generate_cover.py:9API Credential Is Transmitted to an Endpoint Inconsistent with Primary Documentation
scripts/generate_cover.py:22API-Controlled Image Download Permits Blind SSRF and Unbounded Resource Consumption
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
def pilot(body: dict) -> dict:
r = requests.post(
f"{API_BASE}/pilot",
headers={"Authorization": f"Bearer {SKILLBOSS_API_KEY}", "Content-Type": "application/json"},
json=body,
The code clearly performs only the fetching/extraction stage of the declared workflow. It scrapes archive pages and article content, then stores output as markdown plus a manifest. There is no EPUB creation, no cover generation, and no Kindle integration or sending behavior. The supported-site list in code is narrower than the description, omitting at least Wait But Why and Astral Codex Ten. While scraping blogs is aligned with part of the description, the primary end-to-end purpose described is broader than what this code chunk actually does, so this is a material description-behavior mismatch.
The declared purpose centers on acquiring web content from specific blogs or custom sites and transforming it into a Kindle-friendly ebook with an AI-generated cover. This code does none of that. Its sole function is to send a preexisting local file to a Kindle email address through Mail.app. While emailing a finished ebook to Kindle could be a downstream step in a larger workflow, this chunk’s primary behavior is materially different from the declared description and introduces an undeclared local-file email-sending capability.
The skill requests or demonstrates capabilities spanning environment access, filesystem read/write, network access, and shell execution, but it does not declare any explicit tool scope or permissions boundary. That makes it easier for an agent runtime to grant broader access than users expect, increasing risk of unintended scraping, file manipulation, or outbound transmission.
The skill instructs sending generated EPUBs to a Kindle email address without warning users that document contents will be transmitted to an external service. Users may include private material, scraped data, or copyrighted content without understanding that it leaves the local environment.
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.
Use SkillBoss API Hub image generation to create covers. Prompt template:
Book cover for '[Author Name]: [Subtitle]'.
The skill sends cover-generation prompts to a third-party image API but does not warn that prompts and related metadata may be shared externally. If prompts include personal names, reading history, project details, or sensitive themes, that information may be disclosed outside the local system.
This duplicate finding points to the same outbound POST behavior to the SkillBoss endpoint. While the transmission aligns with the stated cover-generation feature, it still creates privacy and policy concerns if prompt content is user-derived and users are not clearly informed.
SKILLBOSS_API_KEY = os.environ["SKILLBOSS_API_KEY"]
result = requests.post(
"https://api.skillbossai.com/v1/pilot",
headers={"Authorization": f"Bearer {SKILLBOSS_API_KEY}", "Content-Type": "application/json"},
json={
This duplicate finding points to the same outbound POST behavior to the SkillBoss endpoint. While the transmission aligns with the stated cover-generation feature, it still creates privacy and policy concerns if prompt content is user-derived and users are not clearly informed.
SKILLBOSS_API_KEY = os.environ["SKILLBOSS_API_KEY"]
result = requests.post(
"https://api.skillbossai.com/v1/pilot",
headers={"Authorization": f"Bearer {SKILLBOSS_API_KEY}", "Content-Type": "application/json"},
json={
The hard-coded remote endpoint confirms the skill communicates with an external service. That is contextually expected here, but any fixed third-party endpoint expands the trust boundary and should be treated as a controlled data egress path rather than silently embedded behavior.
SKILLBOSS_API_KEY = os.environ["SKILLBOSS_API_KEY"]
result = requests.post(
"https://api.skillbossai.com/v1/pilot",
headers={"Authorization": f"Bearer {SKILLBOSS_API_KEY}", "Content-Type": "application/json"},
json={
"type": "image",
Publishing a real default Kindle email address without caution creates a realistic risk of unintended content delivery to another person's device/account. In this context, the skill's purpose is outbound document transmission, so exposing a ready-to-use personal address makes misuse more likely and more damaging.
The documentation exposes a hard-coded personal Kindle email address and presents it as a default delivery target. This can cause accidental delivery of user-generated or scraped content to an unintended recipient and leaks personal contact information embedded in the skill.
The plain-language instructions reveal a real personal Kindle email address for operational reuse. This is dangerous because the skill directly supports automated delivery, so users or downstream agents may send arbitrary content to that personal endpoint, causing privacy, abuse, and harassment risk.
The example pulls a credential from the local keychain and immediately uses it in an external API request without a user-facing warning. This is risky because it silently accesses a local secret store and transmits authenticated traffic off-device, which exceeds normal expectations for a simple blog-to-EPUB workflow.
The manual workflow retrieves an API credential from the local keychain and uses it to call an external image-generation service, expanding the skill from local ebook compilation into credential access and third-party network use. Even if intended for convenience, this creates unnecessary secret handling and outbound data flow that could expose credentials or normalize broader system access than users expect from this skill.
The finding captures the same outbound API request to api.heybossai.com, which is an external transmission outside the local ebook-processing boundary. Although the call appears functionally related to cover generation rather than overtly malicious, it still introduces privacy, dependency, and secret-use risks if performed without clear user awareness.
SKILLBOSS_API_KEY=$(security find-generic-password -a "aineko" -s "api/skillboss" -w) \
python3 -c "
import requests, os, urllib.request
result = requests.post(
'https://api.heybossai.com/v1/pilot',
headers={'Authorization': 'Bearer ' + os.environ['SKILLBOSS_API_KEY'], 'Content-Type': 'application/json'},
json={
The finding captures the same outbound API request to api.heybossai.com, which is an external transmission outside the local ebook-processing boundary. Although the call appears functionally related to cover generation rather than overtly malicious, it still introduces privacy, dependency, and secret-use risks if performed without clear user awareness.
SKILLBOSS_API_KEY=$(security find-generic-password -a "aineko" -s "api/skillboss" -w) \
python3 -c "
import requests, os, urllib.request
result = requests.post(
'https://api.heybossai.com/v1/pilot',
headers={'Authorization': 'Bearer ' + os.environ['SKILLBOSS_API_KEY'], 'Content-Type': 'application/json'},
json={
The hard-coded third-party endpoint identifies a specific external service that receives workflow data during execution. This is not inherently malicious, but in a skill centered on scraping and compilation, an undocumented or automatic transmission to a remote API increases the attack surface and user surprise factor.
python3 -c "
import requests, os, urllib.request
result = requests.post(
'https://api.heybossai.com/v1/pilot',
headers={'Authorization': 'Bearer ' + os.environ['SKILLBOSS_API_KEY'], 'Content-Type': 'application/json'},
json={
'type': 'image',
The workflow includes fully automated outbound email sending via Mail.app and command-line mail tools, which broadens the capability from document preparation to autonomous messaging. This is dangerous because it can send files to recipients without an explicit confirmation step, potentially leaking content or enabling misuse of the user's mail environment.
The Mail.app AppleScript and mutt examples send an email automatically without any warning, preview, or approval checkpoint. In a skill that handles compiled content, silent transmission increases the risk of accidental data exfiltration, wrong-recipient delivery, or abuse if the workflow is adapted or run unattended.
The generated EPUB frontmatter always sets lang: en, which imposes a specific language/locale regardless of the input essays or user preference. Under the policy, forcing a locale without opt-in is a natural-language policy violation.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
print("⚠️ No cover specified! Use --cover to add one.")
print(f"Running pandoc...")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"pandoc error: {result.stderr}")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
from pathlib import Path
SKILLBOSS_API_KEY = os.environ["SKILLBOSS_API_KEY"]
API_BASE = "https://api.heybossai.com/v1"
def pilot(body: dict) -> dict:
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def pilot(body: dict) -> dict:
r = requests.post(
f"{API_BASE}/pilot",
headers={"Authorization": f"Bearer {SKILLBOSS_API_KEY}", "Content-Type": "application/json"},
json=body,
User-supplied cover prompts are transmitted to a third-party image-generation API, but the script provides no explicit notice, consent step, or data-classification guardrails. If users include private reading lists, personal details, or sensitive text in prompts, that data leaves the local environment and is handled by an external provider.
No suspicious patterns detected.