Back to skill

Security audit

WeRead Import

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to export WeRead notes as advertised, but an optional legacy browser mode can copy broad Chrome login and cookie data and expose it through a debug browser session.

Install only if you are comfortable with a skill that writes Markdown files into your chosen directory and uses WeRead account access. Prefer the default Gateway path or isolated browser profile. Avoid WEREAD_PROFILE_SYNC_MODE=legacy unless you understand that it can duplicate broad Chrome cookies and login databases unrelated to WeRead, and avoid passing full cookies directly on the command line.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/open-chrome-debug.sh:14
Finding

Legacy browser-profile synchronization duplicates credentials unrelated to WeRead

Content
View full analysis
&2 mkdir -p "$PROFILE_DIR" # 仅复制保留登录态所需的文件 local item src dest for item in "${SYNC_ITEMS[@]}"; do src="$CHROME_DEFAULT/$item" dest="$PROFILE_DIR/$item" if [ -e "$src" ]; then mkdir -p "$(dirname "$dest")" cp -f "$src" "$dest" fi done echo "同步完成。" >&2 } ``` ### Technical Analysis When `WEREAD_PROFILE_SYNC_MODE=legacy` is enabled, the script copies Chrome's complete cookie databases, saved-login databases, account-login data, encryption state, and security preferences from the user's default profile into a separate profile. These files are not scoped to `weread.qq.com`. They may contain authentication material and metadata for every website used through the source Chrome profile. Copying the raw databases therefore exceeds the minimum privileges required to export WeRead notes. The default `isolated` mode is safer, and the JavaScript cookie extraction logic subsequently filters cookies by the WeRead host. However, host filtering after profile duplication does not protect unrelated credentials already copied into the remote-debugging profile. The copied profile is then launched with a Chrome DevTools Protocol endpoint: ```bash exec "$CHROME_BIN" \ --remote-debugging-port="$PORT" \ --user-data-dir="$PROFILE_DIR" \ "$START_URL" ``` This increases the exposure of the duplicated browser state to processes that can access the profile directory or its debugging endpoint. # ...[truncated 1415 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/run.sh:5
Finding

First-run dependency installation trusts a third-party package mirror and permits lifecycle scripts

Content
View full analysis
&2 (cd "$ROOT_DIR" && npm install --production) fi ``` The lockfile obtains dependencies from a third-party registry mirror: ```json "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ "darwin" ] } ``` ```json "node_modules/playwright": { "version": "1.58.2", "resolved": "https://registry.npmmirror.com/playwright/-/playwright-1.58.2.tgz", "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", "license": "Apache-2.0", "dependencies": { "playwright-core": "1.58.2" } } ``` ```json "node_modules/playwright-core": { "version": "1.58.2", "resolved": "https://registry.npmmirror.com/playwright-core/-/playwright-core-1.58.2.tgz", "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "license": "Apache-2.0" } ``` ### Technical Analysis Running the Skill can implicitly initiate network downloads and execute dependency lifecycle behavior without a separate installation or confirmation step. The dependency artifacts are resolved through `registry.npmmirror.com`, introducing an additional supply-chain trust boundary beyond the package publisher and the canonical npm registry. The lockfile contains SHA-512 integrity values and pins the inst ...[truncated 2235 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (48)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 58)May include surrounding context.

所有环境变量均可参考 env.example.md,复制为 .env 后按需修改:

bash
cp env.example.md .env

输出目录

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is an end-user WeRead note export/sync capability, but the provided code chunk does not interact with WeRead, Markdown generation, Obsidian, books, notes, templates, cookies, or network/login resources. Instead, it is a build/packaging helper that stages the repository into another directory. This is a materially different primary purpose, not merely a supporting implementation detail of note export within the supplied chunk.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/prepare-staging-skill.sh (reported line 15)May include surrounding context.

sh
--exclude 'node_modules' \
  --exclude 'out' \
  --exclude '.DS_Store' \
  --exclude '.env' \
  --exclude '.env.*' \
  "$ROOT_DIR/" "$DEST/"

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/prepare-staging-skill.test.mjs (reported line 29)May include surrounding context.

js
--exclude 'node_modules' \
  --exclude 'out' \
  --exclude '.DS_Store' \
  --exclude '.env' \
  --exclude '.env.*' \
  "$ROOT_DIR/" "$DEST/"

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · tests/prepare-staging-skill.test.mjs (reported line 41)May include surrounding context.

js
--exclude 'node_modules' \
  --exclude 'out' \
  --exclude '.DS_Store' \
  --exclude '.env' \
  --exclude '.env.*' \
  "$ROOT_DIR/" "$DEST/"

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · src/markdown-parser.mjs (reported line 23)May include surrounding context.

js
const end = i + 1 < matches.length ? matches[i + 1].index : text.length;
    const chapterBody = text.slice(start, end).trim();
    if (!chapterBody) continue;
    const entryRegex = new RegExp(`<!-- ${idKind}: ([^>]+) -->([\\s\\S]*?)(?=\\n<!-- ${idKind}: |$)`, 'g');
    const items = [];
    let m;
    while ((m = entryRegex.exec(chapterBody))) {

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · src/merge.mjs (reported line 35)May include surrounding context.

js
.replace(/^###\s*划线\s*$/gm, '')
    .replace(/^###\s*想法\s*$/gm, '')
    .replace(/^###\s+(?!划线\s*$|想法\s*$)(.+)$/gm, '#### $1')
    .replace(/^- time:\s*(.*)$/gm, '<!-- time: $1 -->')
    .replace(/^- chapterUid:\s*(.*)$/gm, '<!-- chapterUid: $1 -->')
    .replace(/^- chapterIdx:\s*(.*)$/gm, '<!-- chapterIdx: $1 -->')
    .replace(/^- range:\s*(.*)$/gm, '<!-- range: $1 -->')

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · src/merge.mjs (reported line 78)May include surrounding context.

js
range: metadataRange || '',
    body: body
      .replace(/<!-- time: [^>]+ -->/g, '')
      .replace(/<!-- chapterUid: [^>]+ -->/g, '')
      .replace(/<!-- chapterIdx: [^>]+ -->/g, '')
      .replace(/<!-- range: [^>]+ -->/g, '')
      .trim(),

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

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · tests/open-chrome-debug.test.mjs (reported line 32)May include surrounding context.

js
s\\n" "$*" >> "${logPath}"\n`, 'utf8');
  await fs.chmod(fakeChrome, 0o755);
  return fakeChrome;
}

async function makeFakeCurl(root, body = '#!/usr/bin/env bash\nexit 0\n') {
  const fakeCurl = path.join(root, 'curl');
  await fs.writeFile(fakeCurl, body, 'utf8');
  await fs.chmod(fakeCurl, 0o755);
  return fakeCurl;
}

describe('open-chrome-debug.sh', () => {
  it('launches an isolated managed Chrome profile without syncing default login data by default', async () => {
    const root = await fs.mkdtemp(path.join(os.tmpdir(), 'weread-open-chrome-'));
    const source = path.join(root, 'source');
    const profile = path.join(root, 'profile');
    const logPath = path.join(root, 'chrome.log');
    const fakeChrome = await makeFakeChrome(root, logPath);
    const fakeCurl = await makeFakeCurl(root, '#!/usr/bin/env bash\nexit 1\n');
    const fakeBinDir = path.dirname(fakeCurl);

    await writeFile(path.join(source, 'Default/Cookies'), 'source-cookie');
    await writeFile(path.join(so

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

L34-L36 明确要求“文档和用户可见的错误提示使用中文”,并进一步规定中文引号及中文错误提示风格。这属于自然语言层面的语言政策约束,但文档中没有说明可由用户选择语言,也没有给出地区限定或合规理由。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README explicitly instructs users to obtain and pass a full WeRead session cookie via CLI argument or environment variable, but does not prominently warn that this cookie is a bearer credential equivalent to account access. In a skill context, users may paste sensitive cookies into shell history, process lists, logs, or shared agent traces, creating a realistic credential exposure path.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill explicitly instructs use of shell commands, network access, and environment variables such as WEREAD_API_KEY, but it does not declare any tool scope or allowed-tools boundary. That weakens containment and increases the chance an agent can invoke more capabilities than users expect, especially given automatic dependency installation and browser-based flows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill is designed to write Markdown into user-specified directories and discusses running against real directories after validation, but it does not prominently warn that normal runs modify user files. In an agent setting, insufficient disclosure about file modification can lead to unintended overwrites, merges, or archival changes in an Obsidian vault or other user content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This manifest-style markdown file presents all setup instructions and labels exclusively in Chinese, which can amount to a language policy violation when no user opt-in or alternative locale is offered. The file does not indicate that the skill is region-specific or that Chinese is an intentional, justified locale restriction.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script can copy Chrome authentication material and profile state, including cookies and login databases, from the user's default browser profile into a separate directory when legacy sync mode is enabled. Duplicating sensitive session artifacts expands the attack surface, can weaken user expectations about where credentials are stored, and may expose authenticated sessions to other local processes, backups, or later misuse without clear informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script launches Chrome with the DevTools remote debugging port enabled, which exposes browser control and, depending on local environment and profile contents, can allow access to authenticated pages, cookies, and page data. In this skill's context, the browser is intended to access WeRead using live login state, so enabling CDP materially increases the sensitivity and abuse potential of the session.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This shell script performs an rsync with the --delete flag, which can remove files from the destination directory, but the file provides no confirmation prompt, warning comment, or user-facing disclosure about that destructive behavior. Because the destination can be user-supplied via the first argument, accidental data loss is possible if the script is pointed at an unexpected path.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
83% confidence
Finding

The script launches a background Chrome debug helper with nohup and then relies on a local CDP endpoint on 127.0.0.1:9222. Persistent browser debug sessions can expose authenticated browser state and cookies to other local processes, and if the spawned Chrome/debug configuration is broader than intended, it can enable unauthorized browser control beyond the lifetime of the import operation.

Content

Scanner excerpt · scripts/run.sh (reported line 30)May include surrounding context.

sh
if curl -s "http://127.0.0.1:$CDP_PORT/json/version" > /dev/null 2>&1; then
    MANAGED_COLD_START=0
  fi
  nohup bash "$SCRIPT_DIR/open-chrome-debug.sh" "$CDP_PORT" > /dev/null 2>&1 </dev/null &
  for i in $(seq 1 10); do
    sleep 1
    if curl -s "http://127.0.0.1:$CDP_PORT/json/version" > /dev/null 2>&1; then

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This function sends HTTP requests to weread.qq.com with a supplied cookie header, which transmits authenticated user/session data over the network. The code does not include any confirmation prompt, user-facing log/print, or inline warning/comment disclosing that authenticated cookies are being sent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The browser fetcher extracts cookies from the existing browser context and performs fetch requests with credentials: 'include', causing authenticated session data to be sent. While errors mention missing login state, there is no explicit warning, confirmation, or user-facing disclosure that the skill will access and use the user's browser session for network calls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The function reads cookies from a browser context and converts them into a Cookie header, which is sensitive credential material. In this file there is no confirmation prompt, user-facing log/print, or explanatory comment/docstring warning that browser authentication cookies will be accessed and used.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code sends user book, bookmark, and review-related data to a remote Tencent Gateway service using authenticated POST requests, but this file contains no explicit consent check, warning, or data-minimization control before transmission. In a note-export skill handling private reading history and annotations, silent remote transfer is privacy-relevant and can surprise users, especially if they expect only local browser/Cookie-based export.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The parser looks specifically for Chinese headings ('划线', '想法') and Chinese inline labels ('摘录', '想法'), which enforces a single locale in the skill behavior. This is a natural-language policy concern because users are not given any opt-in, fallback, or documented language choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file hard-codes Chinese headings and labels such as '已删除', '划线', '想法', and '摘录' in parsing and rendering logic, which makes the generated markdown and expected input format language-specific. There is no visible opt-in, configuration, or justification that this skill is intentionally limited to a Chinese locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code explicitly uses localeCompare(..., 'zh-Hans-CN'), which hard-codes a specific locale for chapter-name sorting. This can violate language/locale policy when users are not given a choice and no region-specific justification is present in the file.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/cli.mjs:405

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
src/cli.mjs:26

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/cli.mjs:313