Back to skill

Security audit

redbook

Security checks for vulnerabilities and agentic risk

Overview

This is a real Xiaohongshu automation tool, but it handles live account cookies and has unsafe install-time and credential-routing behavior that users should review before installing.

Install only if you are comfortable giving this CLI access to live Xiaohongshu/RedNote session cookies and account actions. Back up or check ~/.claude/skills/redbook before npm install, avoid saved cookie files on shared/cloud systems, keep REDBOOK_EDITH_HOST and REDBOOK_CREATOR_HOST unset unless you fully trust the environment, and do not render untrusted markdown with the card renderer.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
src/lib/platform.ts:60
Finding
Session Cookie Exfiltration Through Unrestricted API Host Overrides<![CDATA[ ## Vulnerability Details **File Location**: `src/lib/platform.ts:60-68`; sensitive headers are constructed and transmitted in `src/lib/client.ts:56-105` **Vulnerability Type**: Arbitrary destination for authenticated requests **Risk Level**: Critical ### Vulnerable Code ```ts // src/lib/platform.ts:60-68 export function resolvePlatform(explicit?: string): PlatformConfig { const raw = (explicit || process.env.REDBOOK_PLATFORM || "xhs").toLowerCase(); const base = raw === "rednote" || raw === "global" ? PLATFORMS.rednote : PLATFORMS.xhs; return { ...base, edithHost: process.env.REDBOOK_EDITH_HOST || base.edithHost, creatorHost: process.env.REDBOOK_CREATOR_HOST || base.creatorHost, }; } ``` ```ts // src/lib/client.ts:56-81 private baseHeaders(): Record<string, string> { return { "user-agent": USER_AGENT, "content-type": "application/json", cookie: cookiesToString(this.cookies), origin: this.platform.homeUrl, referer: `${this.platform.homeUrl}/`, }; } private async mainApiGet( uri: string, params?: Record<string, string | number | string[]> ): Promise<unknown> { const fullUri = buildGetUri(uri, params); const url = `${this.platform.edithHost}${fullUri}`; const send = (signFormat: SignFormat) => fetch(url, { method: "GET", headers: { ...this.baseHeaders(), ...signMainApi("GET", uri, this.cookies, params, undefined, undefined, this.platform.signLocation, signFormat), }, }); ``` ```ts // src/lib/client.ts:95-105 private async mainApiPost( uri: string, data: Record<string, unknown> ): Promise<unknown> { const signHeaders = signMainApi("POST", uri, this.cookies, undefined, data, undefined, this.platform.signLocation); const url = `${this.platform.edithHost}${uri}`; const res = await fetch(url, { method: "POST", headers: { ...this.baseHeaders(), ...signHeaders }, body: JSON.stringify(data), }); ``` ### Technical Analysis The client legitimately nee ...[truncated 2380 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `REDBOOK_EDITH_HOST` and `REDBOOK_CREATOR_HOST` overrides from production builds. 2. Allowlist exact authenticated request origins: - `https://edith.xiaohongshu.com` - `https://creator.xiaohongshu.com` - `https://webapi.rednote.com` - `https://creator.rednote.com` 3. Parse destinations with `new URL()` and compare `url.origin` against the allowlist before constructing any request. 4. Refuse credentials on non-HTTPS destinations and reject URLs containing usernames, alternate ports, deceptive suffixes, or subdomains not explicitly approved. 5. Add a second destination check immediately before attaching the `Cookie` header, so future configuration changes cannot bypass the policy. 6. If alternate hosts are required for development, place the feature behind an explicit unsafe-development option that is unavailable in the published CLI. Development requests should use test credentials rather than browser sessions. 7. Add tests confirming that values such as `https://attacker.example`, `http://localhost`, and `https://edith.xiaohongshu.com.attacker.example` cannot receive cookies. 8. Advise users who may have run the CLI with untrusted host overrides to log out and back in to rotate their sessions. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/postinstall.js:27
Finding
Postinstall Script Recursively Deletes an Existing Skill Path<![CDATA[ ## Vulnerability Details **File Location**: `scripts/postinstall.js:27-46` **Vulnerability Type**: Destructive installation-time filesystem operation **Risk Level**: High ### Vulnerable Code ```js if (existsSync(SKILL_LINK)) { try { const stats = lstatSync(SKILL_LINK); if (stats.isSymbolicLink()) { const currentTarget = readlinkSync(SKILL_LINK); if (currentTarget === PACKAGE_ROOT) { console.log('[redbook] Claude Code skill already configured.'); return true; } unlinkSync(SKILL_LINK); } else { rmSync(SKILL_LINK, { recursive: true }); } } catch (err) { console.log(`[redbook] Warning: ${err.message}`); } } symlinkSync(PACKAGE_ROOT, SKILL_LINK); console.log('[redbook] Claude Code skill installed:'); console.log(`[redbook] ~/.claude/skills/redbook -> ${PACKAGE_ROOT}`); return true; ``` ### Technical Analysis The npm `postinstall` lifecycle runs automatically during package installation. The script attempts to register the package as a Claude Code Skill at `~/.claude/skills/redbook`. If that path already exists and is not a symbolic link, the installer invokes: ```js rmSync(SKILL_LINK, { recursive: true }); ``` There is no ownership marker, content validation, backup, confirmation, or requirement that the existing directory was created by this package. Therefore, an unrelated user-managed Skill or other data at the same path is recursively destroyed. Creating a Skill link can support the package's optional integration, but deleting an unknown directory during ordinary npm installation exceeds the privileges necessary to install the CLI. ### Attack Path 1. A user has an existing directory or file at: ```text ~/.claude/skills/redbook ``` 2. The directory contains a custom Skill, local configuration, or other user-controlled data. 3. The user installs or upgrades the package with npm. 4. npm automatically executes `node scripts/postinstall.js`. 5. The script sees tha ...[truncated 800 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never recursively delete a path that lacks a package-specific ownership marker. 2. If `~/.claude/skills/redbook` exists and is not a symlink owned by this package, abort Skill registration and print manual instructions. 3. Move Skill registration out of `postinstall` and into an explicit command such as: ```sh redbook setup-skill ``` 4. Require confirmation before replacing an existing symbolic link that targets another package. 5. If replacement is explicitly requested, rename the existing path to a timestamped backup instead of deleting it. 6. Track package ownership using a narrowly scoped manifest and only remove objects that exactly match the recorded target. 7. Preserve the current safe uninstall behavior that refuses to remove ordinary directories, and tighten its target comparison using canonical paths rather than substring matching. 8. Add installation tests covering existing files, directories, package-owned links, broken links, and links owned by another package. ]]>

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/postinstall.js:55
Finding
Postinstall Script Mutates Integrity-Checked Dependency Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/postinstall.js:55-129` **Vulnerability Type**: Installed tool and dependency modification **Risk Level**: Medium ### Vulnerable Code ```js function patchSweetCookieTimeout() { const target = join( PACKAGE_ROOT, 'node_modules', '@steipete', 'sweet-cookie', 'dist', 'providers', 'chromeSqliteMac.js' ); if (!existsSync(target)) return; try { const content = readFileSync(target, 'utf-8'); const needle = 'timeoutMs: 3_000,'; if (!content.includes(needle)) { // Already patched or upstream fixed return; } const patched = content.replace(needle, 'timeoutMs: options.timeoutMs ?? 30_000,'); writeFileSync(target, patched, 'utf-8'); console.log('[redbook] Patched sweet-cookie keychain timeout (3s -> 30s).'); } catch (err) { console.log(`[redbook] Warning: could not patch sweet-cookie: ${err.message}`); } } function patchSweetCookieBigInt() { const target = join( PACKAGE_ROOT, 'node_modules', '@steipete', 'sweet-cookie', 'dist', 'providers', 'chromeSqlite', 'shared.js' ); if (!existsSync(target)) return; try { const content = readFileSync(target, 'utf-8'); const needle = 'SELECT name, value, host_key, path, expires_utc, samesite, encrypted_value,'; if (!content.includes(needle)) { // Already patched or upstream fixed return; } const patched = content.replace( needle, 'SELECT name, value, host_key, path, CAST(expires_utc AS TEXT) AS expires_utc, samesite, encrypted_value,' ); writeFileSync(target, patched, 'utf-8'); console.log('[redbook] Patched sweet-cookie BigInt overflow (CAST expires_utc).'); } catch (err) { console.log(`[redbook] Warning: could not patch sweet-cookie BigInt: ${err.message}`); } } ``` ### Technical Analysis npm verifies downloaded package artifacts against the integrity values in `package-lock.json`. ...[truncated 2038 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Upgrade to an upstream dependency release that includes the required fixes. 2. If upstream cannot provide the fixes, publish and pin a reviewed fork under a controlled package name. 3. Alternatively, maintain a versioned patch file with an established patching tool and verify: - The exact dependency version. - A cryptographic hash of the original target file. - A cryptographic hash of the patched result. 4. Fail closed when hashes or versions do not match instead of applying approximate string replacements. 5. Document the effective source diff and include it in source-control review. 6. Add CI checks that install from a clean lockfile and verify the resulting dependency tree and file hashes. 7. Prefer implementing compatibility handling in this project's wrapper code where feasible, avoiding mutation of third-party executable files. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/lib/render.ts:526
Finding
Untrusted Markdown Is Processed by Unsandboxed Chrome Without HTML Sanitization<![CDATA[ ## Vulnerability Details **File Location**: `src/lib/render.ts:526-539` and `src/lib/render.ts:582-613` **Vulnerability Type**: Unsafe active-content rendering **Risk Level**: High ### Vulnerable Code ```ts async function markdownToHtml(md: string): Promise<string> { try { const { marked } = await import("marked"); return await marked.parse(md); } catch { console.error(kleur.red("Card rendering requires marked.")); console.error(kleur.dim("Install it with:")); console.error(kleur.dim(" npm install -g marked")); process.exit(1); } } ``` ```ts const browser = await launch.call(puppeteer.default ?? puppeteer, { executablePath: chromePath, headless: true, args: ["--no-sandbox", "--disable-setuid-sandbox", "--disable-gpu"], }); try { const page = await browser.newPage(); await page.setViewport({ width: opts.width, height: opts.height, deviceScaleFactor: opts.dpr, }); // Render cover const coverHtml = buildCoverHtml(frontmatter, style, opts.width, opts.height); await page.setContent(coverHtml, { waitUntil: "domcontentloaded" }); const coverPath = join(opts.outputDir, "cover.png"); await page.screenshot({ path: coverPath, type: "png", clip: { x: 0, y: 0, width: opts.width, height: opts.height }, }); // Render content cards const cardPaths: string[] = []; for (let i = 0; i < pages.length; i++) { const html = await markdownToHtml(pages[i]); const cardHtml = buildCardHtml( html, i + 1, pages.length, style, opts.width, opts.height ); await page.setContent(cardHtml, { waitUntil: "domcontentloaded" }); ``` ### Technical Analysis The renderer passes Markdown to `marked.parse()` and embeds the resulting HTML into a browser page. No sanitizer, content-security policy, JavaScript disablement, URL-scheme validation, or request interception is shown. Markdown parsers commonly preserve embedded HTML unless configured or followed ...[truncated 1935 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Sanitize all generated HTML with a well-maintained allowlist sanitizer before embedding it. 2. Disable raw HTML in Markdown if the selected Markdown library supports that mode. 3. Disable JavaScript on the Puppeteer page before loading content: ```ts await page.setJavaScriptEnabled(false); ``` 4. Enable request interception and reject all network requests. Permit only explicitly generated `data:` resources if needed. 5. Reject dangerous schemes including `javascript:`, remote `http:`/`https:` resources, and unexpected `file:` URLs. 6. Apply a restrictive Content Security Policy, such as denying scripts, frames, objects, connections, and remote media. 7. Remove `--no-sandbox` and `--disable-setuid-sandbox`. If the environment cannot support Chrome sandboxing, fail with a clear error rather than silently disabling it. 8. Run rendering in a separate low-privilege process or container with no credentials, no sensitive mounts, and restricted network access. 9. Add regression tests containing scripts, event handlers, iframes, SVG active content, remote images, localhost URLs, and dangerous URI schemes. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (70)

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Content
Manual trigger via `workflow_dispatch` is also available.

## Build & Test

- `npm run build` — TypeScript compile + chmod
- No test suite yet — verify manually with `redbook whoami`

## Project Structure

- `src/cli.ts` — CLI entry point, 21 commands, `getClient()` is the single cookie→client funnel
- `src/lib/client.ts` — XHS API client (`postComment`, `replyComment`, etc.)
- `src/lib/cookies.ts` — Cookie extraction with Chrome profile auto-discovery
- `src/lib/signing.ts` — Request signing
- `src/lib/analyze.ts` — Viral note analysis and question detection
- `src/lib/reply-strategy.ts` — Batch reply filtering, templating, rate-limited execution
- `src/lib/template.ts` — Viral content template extraction
- `src/lib/health.ts` — Note health check: level detection, sensitive words, tag count
- `src/lib/render.ts` — Card rendering (markdown → PNG via puppeteer-core, optional dep)
- `SKILL.md` — Skill documentation (serves both Claude Code and OpenClaw/ClawHub
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Content
��) |
| `auth` | 保存、导出、检查 Cookie 文件,适合云端/OpenClaw 使用 |

### 通用选项

| 选项 | 说明 | 默认值 |
|------|------|--------|
| `--cookie-source <浏览器>` | Cookie 来源浏览器(chrome, safari, firefox) | `chrome` |
| `--chrome-profile <名称>` | Chrome 配置文件目录名(如 "Profile 1"),默认自动检测 | 自动 |
| `--cookie-string <cookies>` | 手动传入 Cookie 字符串:`"a1=值; web_session=值"`(从 Chrome DevTools 复制) | 无 |
| `--platform <name>` | 强制后端:`xhs`(大陆)或 `rednote`(全球版),不传则自动检测 | 自动 |
| `--global` | 强制使用全球版 RedNote 后端(等同 `--platform rednote`) | 无 |
| `--json` | JSON 格式输出 | `false` |

### 保存 Cookie / 云端使用

如果在 OpenClaw、云服务器或 CI 里运行,不想每条命令都加 `--cookie-string`,可以把 Cookie 保存成文件。普通命令会按这个顺序读取 Cookie:`--cookie-string` �
Confidence
95% confidence
Finding
The skill explicitly instructs users and AI agents to extract browser cookies, pass them on the command line, save them to files, and reuse them for authentication. Browser session cookies are plaintext bearer credentials; exposing them through CLI args, environment variables, cloud uploads, or automation can leak account access via shell history, process listings, logs, CI output, or compromised agent environments. In context, this is more dangerous because the tool is designed for agent-driven automation and cloud/OpenClaw use, which increases the chance that secrets are copied, persisted, or exfiltrated outside the user’s browser trust boundary.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documentation discusses generating anti-bot API signatures, browser/device fingerprint material, and alternate signing formats to access protected APIs. That is not inherently malware, but it is a sensitive capability that exceeds a simple content-analysis description and can facilitate stealthier authenticated automation against protected services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documentation discusses generating anti-bot API signatures, browser/device fingerprint material, and alternate signing formats to access protected APIs. That is not inherently malware, but it is a sensitive capability that exceeds a simple content-analysis description and can facilitate stealthier authenticated automation against protected services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documentation discusses generating anti-bot API signatures, browser/device fingerprint material, and alternate signing formats to access protected APIs. That is not inherently malware, but it is a sensitive capability that exceeds a simple content-analysis description and can facilitate stealthier authenticated automation against protected services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documentation discusses generating anti-bot API signatures, browser/device fingerprint material, and alternate signing formats to access protected APIs. That is not inherently malware, but it is a sensitive capability that exceeds a simple content-analysis description and can facilitate stealthier authenticated automation against protected services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documentation discusses generating anti-bot API signatures, browser/device fingerprint material, and alternate signing formats to access protected APIs. That is not inherently malware, but it is a sensitive capability that exceeds a simple content-analysis description and can facilitate stealthier authenticated automation against protected services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documentation discusses generating anti-bot API signatures, browser/device fingerprint material, and alternate signing formats to access protected APIs. That is not inherently malware, but it is a sensitive capability that exceeds a simple content-analysis description and can facilitate stealthier authenticated automation against protected services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documentation discusses generating anti-bot API signatures, browser/device fingerprint material, and alternate signing formats to access protected APIs. That is not inherently malware, but it is a sensitive capability that exceeds a simple content-analysis description and can facilitate stealthier authenticated automation against protected services.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The documentation discusses generating anti-bot API signatures, browser/device fingerprint material, and alternate signing formats to access protected APIs. That is not inherently malware, but it is a sensitive capability that exceeds a simple content-analysis description and can facilitate stealthier authenticated automation against protected services.

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Content
safe band, not guesswork. Community crawlers ([MediaCrawler](https://github.com/NanmiCoder/MediaCrawler)) default to **~2 s/request, single-threaded** (`CRAWLER_MAX_SLEEP_SEC = 2`, `MAX_CONCURRENCY_NUM = 1`); reverse-engineering write-ups put the "looks-human" frequency at **3–8 s/request** and the per-IP ceiling at **≤5 requests/min** (~12 s average). This skill runs on your **real logged-in cookies + residential IP + real Chrome fingerprint** — the *lowest*-detection profile (the thing scrapers spend most of their effort faking). So the binding risk isn't request signature, it's **behavioral**: a human doesn't open 100 note-detail pages in two minutes. We therefore pace to a human reading cadence — comfortably inside the safe band — rather than to the absolute minimum. (5-minute gaps, an earlier guess, are ~25× slower than the ceiling and buy nothing.)

### The real rule: behave like a human reading (not "go slow")

Detection here is **distributional, not a rate threshold.
Confidence
93% confidence
Finding
The text normalizes use of 'real logged-in cookies + residential IP + real Chrome fingerprint' to minimize detection. In context this is not proof of malware, but it does confirm the tool is designed to leverage live user session credentials and browser identity for stealthier automated access, which is sensitive and increases misuse potential.

Credential Access

High
Category
Privilege Escalation
Content
- Node.js >= 22
- Logged into xiaohongshu.com in Chrome (or Safari/Firefox with `--cookie-source`)
- macOS (cookie extraction uses native keychain access)
- **For card rendering only:** `puppeteer-core` and `marked` (`npm install -g puppeteer-core marked`). Uses your existing Chrome — no additional browser download.
Confidence
97% confidence
Finding
The skill explicitly relies on native keychain-backed browser cookie extraction to access Xiaohongshu sessions. Credential access is dangerous because extracted cookies can be reused to impersonate the user, perform account actions, and potentially expose private account data if stored or logged insecurely.

Self-Modification

High
Category
Rogue Agent
Content
2. **Add persona-based reply** — extend `batch-reply` with `--persona <file>` option
3. **Add Gemini cover generation** — new `generate-cover` command with optional `@google/genai` dep
4. **Add Module L** to SKILL.md — AI Cover Generation analysis module
5. **Update SKILL.md metadata** — add `requires.env` for `GEMINI_API_KEY` (optional)
6. **Add `redbook monitor`** — simple comment monitoring loop with configurable interval

---
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Known Vulnerable Dependency: basic-ftp==5.2.0 — 4 advisory(ies): GHSA-6v7q-wjvx-w8wg (basic-ftp: Incomplete CRLF Injection Protection Allows Arbitrary FTP Command Exe); CVE-2026-39983 (basic-ftp has FTP Command Injection via CRLF); CVE-2026-41324 (basic-ftp vulnerable to denial of service via unbounded memory consumption in Cl) +1 more

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: extract-zip==2.0.1 — 2 advisory(ies): CVE-2026-19693 (extract-zip allows arbitrary file writes through symlink archive entries); CVE-2026-56876 (extract-zip unvalidated symlink path traversal)

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: ip-address==10.1.0 — 2 advisory(ies): CVE-2026-69192 (ip-address: Address4 decodes leading-zero octets as decimal while resolvers deco); CVE-2026-42338 (ip-address has XSS in Address6 HTML-emitting methods)

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
80% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Credential Access

High
Category
Privilege Escalation
Content
}

/**
 * Patch @steipete/sweet-cookie keychain timeout bug.
 *
 * Published v0.1.0 hardcodes `timeoutMs: 3_000` in chromeSqliteMac.js,
 * ignoring the caller's value. The macOS `security` CLI often needs >3s
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
}

/**
 * Patch @steipete/sweet-cookie keychain timeout bug.
 *
 * Published v0.1.0 hardcodes `timeoutMs: 3_000` in chromeSqliteMac.js,
 * ignoring the caller's value. The macOS `security` CLI often needs >3s
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
}

/**
 * Patch @steipete/sweet-cookie keychain timeout bug.
 *
 * Published v0.1.0 hardcodes `timeoutMs: 3_000` in chromeSqliteMac.js,
 * ignoring the caller's value. The macOS `security` CLI often needs >3s
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
}

/**
 * Patch @steipete/sweet-cookie keychain timeout bug.
 *
 * Published v0.1.0 hardcodes `timeoutMs: 3_000` in chromeSqliteMac.js,
 * ignoring the caller's value. The macOS `security` CLI often needs >3s
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp1

High
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The CLI reads environment variables such as REDBOOK_COOKIE_FILE, REDBOOK_PLATFORM, and REDBOOK_COOKIE_STRING, which expands its authority beyond what the manifest reportedly declares. In an agent-skill setting, understated environment access is dangerous because it allows the skill to consume secrets or alter behavior from ambient process state without explicit user awareness.

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Content
oin(homedir(), ".redbook");
const DEFAULT_COOKIE_FILE = join(REDBOOK_DIR, "cookies.json");

const program = new Command();

program
  .name("redbook")
  .description("CLI tool for Xiaohongshu (Red Note)")
  .version(pkg.version);

// Global option for cookie source
function addCookieOption(cmd: Command): Command {
  return cmd
    .option(
      "--cookie-source <browser>",
      "Browser to read cookies from (chrome, safari, firefox)",
      "chrome"
    )
    .option(
      "--chrome-profile <name>",
      'Chrome profile directory name (e.g., "Profile 1")'
    )
    .option(
      "--cookie-string <cookies>",
      'Manual cookie string: "a1=VALUE; web_session=VALUE" (from Chrome DevTools)'
    )
    .option(
      "--platform <name>",
      "Force backend: 'xhs' (mainland xiaohongshu.com) or 'rednote' (global rednote.com). Default: auto-detect from your login."
    )
    .option(
      "--global",
      "Force the global RedNote backend (shorthand for --platform rednote)"
    );
}
Confidence
89% confidence
Finding
The info-stealer signature is triggered by code that reads cookies directly from installed browsers, which is a real credential-harvesting capability even if presented as a convenience feature. In this skill's context, that capability is especially risky because the same tool can immediately use those cookies to perform authenticated reads and account mutations on behalf of the user.

Lp1

High
Category
MCP Least Privilege
Confidence
97% confidence
Finding
This module performs undisclosed network-capable behavior by probing a local HTTP DevTools endpoint and opening a WebSocket connection to Chrome. Even though the traffic is loopback-only, attaching to a browser debugging session exposes highly sensitive browser state and should be explicitly declared because it materially expands the skill's privilege surface.

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Content
/**
 * CDP (Chrome DevTools Protocol) cookie extraction fallback.
 *
 * When sweet-cookie can't fully decrypt Chrome cookies on Windows
 * (Chrome 127+ uses App-Bound Encryption), this module connects to
 * Chrome via its DevTools Protocol to read cookies directly — Chrome
 * itself handles decryption, so all cookies are readable.
 *
 * Flow:
 *  1. Check for an existing Chrome debugging session on port 9222
 *  2. If unavailable, launch Chrome headless with --remote-debugging-port
 *  3. Use Network.getAllCookies via WebSocket to read decrypted cookies
 *  4. Shut down headless Chrome if we launched it
 */

import { spawn, execFileSync, type ChildProcess } from "node:child_process";
import { existsSync, mkdtempSync, mkdirSync, copyFileSync, rmSync } from "node:fs";
import { homedir, tmpdir } from "node:os";
import { join } from "node
Confidence
92% confidence
Finding
The YARA hit is supported by the module's actual behavior: it deliberately obtains decrypted Chrome cookies, including by launching/attaching to CDP and copying profile data to bypass profile-lock issues. While the apparent goal is service automation rather than credential theft, these are the same primitives used by information stealers and they create a real risk of browser-session compromise if misused.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/lib/cdp-cookies.ts:173