Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Castreader Openclaw Skill

v3.2.14

URL to audio: extract any web page and convert to natural AI speech (Kokoro TTS). The only skill that turns a URL into a podcast-quality MP3 — no API key nee...

1· 589·1 current·1 all-time

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for vinxu/castreader.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "Castreader Openclaw Skill" (vinxu/castreader) from ClawHub.
Skill page: https://clawhub.ai/vinxu/castreader
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install castreader

ClawHub CLI

Package manager switcher

npx clawhub@latest install castreader
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
medium confidence
Purpose & Capability
The skill is a URL/book-to-audio tool and its code (extractor bundle, puppeteer-based extraction, and TTS calls) matches that purpose. It also reads a local library directory (~/castreader-library/books/) for synced books — this is consistent with the 'read books' capability. Small mismatch: the SKILL metadata does not list environment variables (CASTREADER_API_URL/VOICE/API_KEY) even though the scripts use them; README documents them.
Instruction Scope
SKILL.md instructs the agent to run npm install and then use the provided node scripts only. Those scripts (extract/read-url/sync-books/generate-text) perform web browsing via Puppeteer, inject extractor-bundle.js into target pages, read/write files under /tmp and the user's home castreader-library, and POST extracted text to an external TTS endpoint (default https://api.castreader.ai). All of these actions are within the stated scope, but they do involve sending extracted webpage/book text off-host (privacy consideration).
Install Mechanism
There is no automated install spec in the registry, but SKILL.md insists on running `npm install` in the skill directory. package.json depends on puppeteer, which will fetch many npm packages and download a Chromium binary during install — a moderate-risk, high-footprint operation. The packages come from the npm registry (no obscure URLs), but you should expect a substantial download and native resource use.
!
Credentials
The skill does not declare required env vars in registry metadata, but the code reads optional environment variables: CASTREADER_API_URL, CASTREADER_API_KEY, CASTREADER_VOICE, CASTREADER_SPEED. Using an API_KEY (if provided) would send that secret to the TTS API on requests. The scripts also read files under the user's home directory (~/castreader-library/books/) — appropriate for reading synced books but potentially sensitive. Overall the requested/used env and filesystem access are explainable for the feature set but the registry metadata omission and the fact that extracted text is posted to an external API are notable concerns.
Persistence & Privilege
The skill does not request 'always: true', does not modify other skills or system settings, and does not persist agent-wide configuration. It runs as-invoked (node scripts) and does not request elevated privileges beyond normal filesystem and network access for the current user.
Scan Findings in Context
[uses-puppeteer] expected: Puppeteer is necessary for headless browsing and page extraction; install will download Chromium which increases install footprint and network activity.
[external-tts-api-calls] expected: scripts call POST {CASTREADER_API_URL}/api/captioned_speech_partly and will upload text to that endpoint (default https://api.castreader.ai). This is expected for a TTS service but implies extracted webpage/book text is transmitted to an external service.
[reads-home-directory-castreader-library] expected: sync-books.js reads ~/castreader-library/books/* to enumerate and open book files — expected for book-reading functionality, but this is access to local user files.
Assessment
What to consider before installing: - Network & privacy: The skill extracts webpage text and book files and sends that text to an external TTS API (default https://api.castreader.ai). If pages or books contain sensitive data, do not use the online TTS mode. The API key is optional; if you set CASTREADER_API_KEY it will be included in requests to the API. - Install footprint: You must run `npm install` in the skill folder. That will install Puppeteer and many npm packages and will download a Chromium binary — expect a large download and extra disk space. Prefer running in a sandbox, container, or VM if you are cautious. - Local file access: The skill will read from ~/castreader-library/books/ for synced books. Ensure only intended files are stored there before using the book features. - Code review & testing: If you want to be extra safe, inspect the included scripts (they are present) and test extraction-only mode (run `node scripts/read-url.js <url> 0`) offline to verify extraction behavior without generating TTS. You can also run `npm install --no-audit` in an isolated environment and monitor network traffic. - Metadata mismatch: The registry metadata didn't declare the environment variables the scripts use — be aware and set/omit CASTREADER_API_KEY and CASTREADER_API_URL intentionally. If these observations are acceptable, the skill appears to do what it claims. If not, consider an offline/local TTS alternative or running the tool in an isolated environment.
scripts/read-url.js:133
Shell command execution detected (child_process).
scripts/generate-text.js:16
Environment variable access combined with network send.
scripts/read-url.js:29
Environment variable access combined with network send.
scripts/sync-books.js:38
Environment variable access combined with network send.
!
scripts/generate-text.js:103
File read combined with network send (possible exfiltration).
!
scripts/read-url.js:130
File read combined with network send (possible exfiltration).
!
scripts/sync-books.js:130
File read combined with network send (possible exfiltration).
Patterns worth reviewing
These patterns may indicate risky behavior. Check the VirusTotal and OpenClaw results above for context-aware analysis before installing.

Like a lobster shell, security has layers — review code before you run it.

Runtime requirements

🔊 Clawdis
OSmacOS · Linux · Windows
Any binnode
latestvk974y3dxbn6jew0ead3ygtam6583wknj
589downloads
1stars
35versions
Updated 4h ago
v3.2.14
MIT-0
macOS, Linux, Windows

CastReader — Read Web Pages & Books Aloud

Setup (once per session)

cd <skill-directory> && npm install

How to find target (chatId)

User messages look like: [Telegram username id:8716240840 ...] The number after id: is the target. You MUST use this number in every message tool call. Example: target is "8716240840".


Mode A: When user sends a URL

Step 1: Extract article

node scripts/read-url.js "<url>" 0

Returns: { title, language, totalParagraphs, totalCharacters, paragraphs[] }

Step 2: Show info + ask user to choose

Reply with this text:

📖 {title}
🌐 {language} · 📝 {totalParagraphs} paragraphs · 📊 {totalCharacters} chars

📋 Summary:
{write 2-3 sentence summary from paragraphs}

Reply a number to choose:
1️⃣ Listen to full article (~{totalCharacters} chars, ~{Math.ceil(totalCharacters / 200)} sec to generate)
2️⃣ Listen to summary only (~{summary_char_count} chars, ~{Math.ceil(summary_char_count / 200)} sec to generate)

STOP. Wait for user to reply 1 or 2.

Step 3a: User chose 1 (full article)

Reply: 🎙️ Generating full audio (~{totalCharacters} chars, ~{Math.ceil(totalCharacters / 200)} seconds)...

node scripts/read-url.js "<url>" all

Then send the audio file using the message tool:

{"action":"send", "target":"<chatId>", "channel":"telegram", "filePath":"<audioFile>", "caption":"🔊 {title}"}

Reply: ✅ Done!

Step 3b: User chose 2 (summary only)

Reply: 🎙️ Generating summary audio...

Save the SAME summary text you showed in Step 2 to a file and generate:

echo "<summary text>" > /tmp/castreader-summary.txt
node scripts/generate-text.js /tmp/castreader-summary.txt <language>

Then send the audio file using the message tool:

{"action":"send", "target":"<chatId>", "channel":"telegram", "filePath":"/tmp/castreader-summary.mp3", "caption":"📋 Summary: {title}"}

Reply: ✅ Done!


Mode B: When user asks to read a book (微信读书 / Kindle)

Books are synced from WeChat Reading or Kindle to ~/castreader-library/books/. Each book is stored in a folder like 书名-hashid (e.g. 儒林外史-dc532c705c6d3edc5503acc).

⚠️ CRITICAL: You MUST use sync-books.js --list to get the exact book folder ID. NEVER guess or construct the folder path yourself. The folder name includes a title prefix that you cannot predict.

Step 1: List available books

node scripts/sync-books.js --list

Returns: { books: [{ id, title, author, language, totalChapters, totalCharacters, source, syncedAt }] }

The id field is the exact folder name you must use in all subsequent commands. Example: "儒林外史-dc532c705c6d3edc5503acc".

Step 2: Show book list and let user choose

Reply with the book list:

📚 Your synced books:

1. 📖 {title} — {author}
   🌐 {language} · 📑 {totalChapters} chapters · 📊 {totalCharacters} chars · 📱 {source}

2. ...

Reply the number of the book you want to read.

STOP. Wait for user to choose a book.

Step 3: Show chapter list and let user choose

node scripts/sync-books.js --book "<id>"

Use the exact id from Step 1 output. Returns the book content with chapter list.

Reply:

📖 {title} — {author}
📑 {totalChapters} chapters · 📊 {totalCharacters} chars

📋 Chapters:
1. {chapter 1 title}
2. {chapter 2 title}
...

Reply a number to listen to a chapter, or "all" to listen to the full book.

STOP. Wait for user to choose.

Step 4a: User chose a chapter number

node scripts/sync-books.js --book "<id>" --chapter <num> --audio

Returns: { title, audioFile, fileSizeBytes }

Send the audio:

{"action":"send", "target":"<chatId>", "channel":"telegram", "filePath":"<audioFile>", "caption":"🔊 {bookTitle} — Chapter {num}"}

Step 4b: User chose "all" (full book)

node scripts/sync-books.js --book "<id>" --audio

Returns: { title, audioFile, fileSizeBytes }

Send the audio:

{"action":"send", "target":"<chatId>", "channel":"telegram", "filePath":"<audioFile>", "caption":"🔊 {bookTitle} (full)"}

Reading a chapter as text (no audio)

If the user wants to read (not listen), use without --audio:

node scripts/sync-books.js --book "<id>" --chapter <num>

Returns: { title, author, language, chapter: { number, title, text }, totalChapters }


Rules

  • ALWAYS extract first (index=0 for URLs, --list for books), show info, wait for user choice. Never skip.
  • ALWAYS send audio files using the message tool with target (numeric chatId) and channel ("telegram"). Never just print the file path.
  • For books: ALWAYS run --list first and use the exact id from the output. NEVER construct book paths manually or use partial IDs.
  • Do NOT use built-in TTS tools. ONLY use read-url.js, generate-text.js, and sync-books.js.
  • Do NOT use web_fetch. ONLY use read-url.js.
  • Do NOT use the read tool to directly access files in ~/castreader-library/. ONLY use sync-books.js.

Comments

Loading comments...