Back to skill

Security audit

News To Markdown

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but its launcher can execute a locally resolved npm package without verifying the exact package version or integrity.

Review before installing. Use only the pinned npm install path in an isolated or low-privilege environment, avoid the floating npx examples, and do not run the launcher from untrusted project directories unless the package resolution issue is fixed.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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)

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/run.js:120
Finding

Unverified Local Package Resolution Enables Arbitrary Code Execution

Content
View full analysis

Vulnerability Details

File Location: scripts/run.js:120-139, scripts/run.js:164-180
Vulnerability Type: Untrusted local module resolution and missing dependency verification
Risk Level: High

Vulnerable Code

js
function resolveCliEntry() {
  const nodeBinDir = path.dirname(process.execPath);
  const candidateRoots = [
    path.join(nodeBinDir, '..', 'lib', 'node_modules'),
    path.join(nodeBinDir, 'node_modules'),
    path.join(__dirname, '..', 'node_modules'),
    path.join(process.cwd(), 'node_modules'),
  ];

  for (const root of candidateRoots) {
    const candidate = path.join(root, PINNED_PACKAGE, 'dist', 'cli.js');
    try {
      if (fs.statSync(candidate).isFile()) return candidate;
    } catch (_) { /* not present at this root; continue */ }
  }

  try {
    return require.resolve(`${PINNED_PACKAGE}/dist/cli.js`, { paths: candidateRoots });
  } catch (_) {
    return null;
  }
}
js
const cliEntry = resolveCliEntry();
if (!cliEntry) {
  fail(
    `'${PINNED_PACKAGE}' not found in any standard node_modules location. ` +
    `Install it first: npm install -g ${PINNED_PACKAGE}@${REQUIRED_VERSION}`,
  );
}

process.argv = [process.execPath, cliEntry, ...cliArgs];

try {
  require(cliEntry);
} catch (err) {
  fail(`Failed to invoke ${PINNED_PACKAGE}: ${err && err.message ? err.message : err}`);
}

Technical Analysis

The launcher includes process.cwd()/node_modules among the trusted package roots and subsequently executes the resolved CLI through require(). The current working directory can be controlled by the caller or influenced by the directory from which an agent invokes the Skill.

Although the launcher declares REQUIRED_VERSION = '3.3.1', it never reads the resolved package's package.json, compares its version with the required version, or verifies package integrity. The constant is only used in help and error mes ...[truncated 1888 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove process.cwd()/node_modules from the candidate roots. Do not load executable dependencies from caller-controlled directories.
  2. Resolve the package only from a dedicated, administrator-controlled installation root or bundle the reviewed dependency with a lockfile.
  3. Read the resolved package's package.json and require an exact version match with 3.3.1 before loading its CLI.
  4. Canonicalize the package root and CLI path with fs.realpathSync() and verify that the resulting path remains beneath the approved installation directory.
  5. Reject symbolic links or other path redirections that escape the trusted root.
  6. Verify the installed package against a pinned cryptographic integrity value, such as the expected npm tarball integrity hash.
  7. Prefer running the third-party converter in a restricted subprocess or sandbox with narrowly scoped filesystem and network permissions rather than loading it into the agent process.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:73
Finding

Documented Floating-Version npx Command Executes Unpinned Third-Party Code

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:73-78, SKILL.md:309-310, README.md:21-26
Vulnerability Type: Unpinned runtime dependency retrieval and execution
Risk Level: Medium

Vulnerable Command

bash
npx --yes news-to-markdown@^3.3.1 --url "https://www.toutiao.com/article/123"

Technical Analysis

The documented alternative execution path uses the semantic-version range ^3.3.1. This range can resolve to a future package release rather than the version reviewed when the Skill was published. The command uses npx --yes, which can download and immediately execute the selected package without interactive confirmation.

This path has no project lockfile or pinned integrity value establishing the exact package artifact that will run. Therefore, its effective code can change after the Skill has been audited. The documentation explicitly warns about this risk and recommends sandboxing, but it still presents the command as an available execution path; the warning does not technically prevent unsafe execution.

Attack Path

  1. An attacker compromises the npm package, its publisher account, or a future release satisfying ^3.3.1.
  2. The compromised version is published to the npm registry.
  3. A user or agent follows the documented alternative command.
  4. npx resolves the newest compatible package version and downloads it.
  5. The downloaded package executes immediately with the permissions of the invoking user.
  6. Malicious package lifecycle or CLI code performs attacker-selected operations.

Impact Assessment

A compromised dependency can execute arbitrary JavaScript with the privileges of the invoking account. It may read accessible files and environment variables, exfiltrate credentials, alter generated Markdown, modify writable files, or communicate with arbitrary remote services.

The scope includes all resources available to the terminal or agent process. Isolation advice in ...[truncated 152 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the floating-version npx path from the documentation.
  2. If an npx alternative is necessary, use the exact reviewed version:
    bash
    npx --yes news-to-markdown@3.3.1 --url "https://www.toutiao.com/article/123"
    
  3. Pin and verify the expected npm artifact integrity rather than relying only on a version string.
  4. Provide a lockfile or a reproducible installation procedure for the complete transitive dependency graph.
  5. Execute downloaded third-party tools only inside an enforced container or sandbox with read-only source files, a dedicated output directory, no inherited secrets, and restricted network access.
  6. Apply the same hardening consistently in SKILL.md and README.md so users are not directed toward a less secure alternative.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (12)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The primary skill description at L03 is written as a directive in Chinese ('输入文章 URL,输出干净的 Markdown 正文') and the rest of the README continues exclusively in Chinese. There is no indication that users may choose another language or that the skill is intentionally limited to a Chinese-only regional context, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
85% confidence
Finding

npx playwright install chromium fetches and runs package-managed installation logic and downloads a browser binary at execution time without any version pinning shown in the README. In an agent-oriented skill, this increases supply-chain exposure and non-determinism, especially if run automatically in shared or persistent environments.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill documents shell-based execution paths (node, npm, npx) but does not declare any explicit tool scope such as permissions or allowed-tools. In an agent environment, that omission weakens least-privilege controls and can allow broader command execution than the skill actually needs, increasing the blast radius if the skill or its dependencies are abused.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

npx playwright install chromium invokes an unpinned package resolution path and then downloads and installs a large remote browser binary. In an agent or automation context, this expands the supply-chain attack surface to both the npm package resolver and external binary distribution, which is especially sensitive because the result is executable code on the host.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

This npx playwright installation path is a real supply-chain concern because it resolves package code at execution time and installs executable browser components from remote sources. In a skill intended for agents that fetch arbitrary web content, adding dynamic browser installation increases risk if the environment is not tightly sandboxed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The user-facing help text is largely presented in Chinese, including usage, commands, options, supported platforms, and examples. This imposes a specific language on users without any opt-in, fallback, or justification that the skill is region-specific, which matches the language/locale policy-violation category.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This manifest is a JSON file, so SQP-3 applies. The only user-facing command description is written in Chinese ("将新闻文章转换为 Markdown") with no indication that the skill is Chinese-only or that users may choose another language, which can violate a language/locale policy requiring opt-in or documented justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.