Back to skill

Security audit

OpenClaw Skill: Obsidian Markdown to Cloudflare Pages

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent publishing purpose, but its implementation can run unpinned third-party code, mishandle credentials, and delete or mutate local files more broadly than users may expect.

Install only if you are comfortable auditing and hardening the script first. Use a dedicated empty workspace, scoped Cloudflare token, uncommitted secret files, test project/subdomain, and avoid Basic Auth passwords in config until credential handling and generated middleware are fixed.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
bin/publishmd-cf.js:41
Finding

Shell Command Injection Through Untrusted Configuration Values

Content
View full analysis
`--exclude '${f}/'`) .join(' '); sh(`rsync -av --exclude '.obsidian/' --exclude '*.canvas' ${excludes} "${src}/" "${dest}/${folder}/"`); ``` ```javascript const envPrefix = [ `CLOUDFLARE_API_TOKEN="${token.replace(/"/g, '\\"')}"`, accountId ? `CLOUDFLARE_ACCOUNT_ID="${accountId.replace(/"/g, '\\"')}"` : '' ].filter(Boolean).join(' '); sh(`${envPrefix} npx wrangler pages deploy public --project-name "${project}" --branch "${branch}"`, workspaceDir); ``` ### Technical Analysis The `sh()` helper passes dynamically constructed strings to `execSync()`, which invokes a shell. Multiple values originating from `config.json`, `.env`, or wizard input are interpolated into these strings. Quoting does not provide adequate protection. Values placed inside double quotes can still contain shell substitutions such as `$(command)` or backticks. The Cloudflare token handling escapes only double-quote characters and does not neutralize command substitutions, backslashes, newlines, or other shell syntax. The single-quoted `rsync` exclusion values can escape their quoting context by containing a single quote. Affected values include source and exclusion folder names, workspace paths, Cloudfl ...[truncated 1175 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
bin/publishmd-cf.js:288
Finding

Configurable Recursive Deletion Can Escape the Quartz Workspace

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
bin/publishmd-cf.js:342
Finding

Unpinned Third-Party Code Is Downloaded and Executed

Content
View full analysis
0) { if (!ALLOW_DESTRUCTIVE) { throw new Error('Fallback bootstrap requires clearing workspaceDir. Re-run with ALLOW_DESTRUCTIVE=1 or use an empty workspace directory.'); } clearDirectoryContents(workspaceDir); } sh(`git clone https://github.com/jackyzha0/quartz.git "${workspaceDir}"`); sh('npm i', workspaceDir); bootstrapOk = fs.existsSync(path.join(workspaceDir, 'quartz.config.ts')); } ``` ```javascript function build() { const cfg = loadConfig(); const workspaceDir = expandHome(cfg.publish.workspaceDir); sh('npx quartz build', workspaceDir); ``` ```javascript sh(`${envPrefix} npx wrangler pages deploy public --project-name "${project}" --branch "${branch}"`, workspaceDir); ``` ### Technical Analysis The workflow uses `npx` without explicit package versions and can clone the mutable default branch of the Quartz repository. It subsequently runs `npm i`, which can execute package lifecycle scripts. No reviewed lockfile, commit hash, release tag, package integrity value, or signature is enforced by this project. As a result, the effective code executed during setup, build, or deployment can differ from the code available when this Skill was audited. The referenc ...[truncated 1299 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
bin/publishmd-cf.js:483
Finding

Basic Authentication Credentials Are Persisted and Embedded in Plaintext

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
bin/publishmd-cf.js:437
Finding

Dry-Run Mode Performs Filesystem Mutations Despite Non-Mutating Documentation

Content
View full analysis
/index.html ✅`); } // Config-driven branding. const domain = inferDomain(cfg); const clippingsLabel = cfg?.site?.branding?.clippingsIndexLabel || `${rootSourceFolder} | ${domain}`; const rootLabel = cfg?.site?.branding?.rootIndexLabel || `Vault | ${domain} ...[truncated 1965 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (21)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description understates the skill's real capabilities, which include reading local Obsidian configuration, modifying generated site content, handling credentials, and performing destructive cleanup. This mismatch is dangerous because users or orchestrators may grant trust based on the benign description while the skill performs broader filesystem, network, and secret-handling actions.

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 · README.md (reported line 121)May include surrounding context.

Option B: skill-local env file (recommended for this skill)

bash
cp skills/obsidian-cloudflare-pages/.env.example skills/obsidian-cloudflare-pages/.env
# then edit .env
# optional auth envs: BASIC_AUTH_USERNAME / BASIC_AUTH_PASSWORD

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 122)May include surrounding context.

Option B: skill-local env file (recommended for this skill)

bash
cp skills/obsidian-cloudflare-pages/.env.example skills/obsidian-cloudflare-pages/.env
# then edit .env
# optional auth envs: BASIC_AUTH_USERNAME / BASIC_AUTH_PASSWORD

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 · SKILL.md (reported line 85)May include surrounding context.

Option B: skill-local env file (recommended for this skill)

bash
cp skills/obsidian-cloudflare-pages/.env.example skills/obsidian-cloudflare-pages/.env
# then edit .env
# optional auth envs: BASIC_AUTH_USERNAME / BASIC_AUTH_PASSWORD

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 · SKILL.md (reported line 86)May include surrounding context.

Option B: skill-local env file (recommended for this skill)

bash
cp skills/obsidian-cloudflare-pages/.env.example skills/obsidian-cloudflare-pages/.env
# then edit .env
# optional auth envs: BASIC_AUTH_USERNAME / BASIC_AUTH_PASSWORD

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 · SKILL.md (reported line 127)May include surrounding context.

Option B: skill-local env file (recommended for this skill)

bash
cp skills/obsidian-cloudflare-pages/.env.example skills/obsidian-cloudflare-pages/.env
# then edit .env
# optional auth envs: BASIC_AUTH_USERNAME / BASIC_AUTH_PASSWORD

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 · SKILL.md (reported line 128)May include surrounding context.

Option B: skill-local env file (recommended for this skill)

bash
cp skills/obsidian-cloudflare-pages/.env.example skills/obsidian-cloudflare-pages/.env
# then edit .env
# optional auth envs: BASIC_AUTH_USERNAME / BASIC_AUTH_PASSWORD

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 125)May include surrounding context.

md
node bin/publishmd-cf.js init

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 126)May include surrounding context.

md
node bin/publishmd-cf.js init

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 129)May include surrounding context.

md
node bin/publishmd-cf.js init

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 · bin/publishmd-cf.js (reported line 35)May include surrounding context.

js
}

// Load skill-local env vars if present (without overriding shell env)
loadDotEnv(path.join(root, '.env'));

function expandHome(p) {
  return p?.startsWith('~/') ? path.join(os.homedir(), p.slice(2)) : p;

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

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.

Content

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

md
Commands:

- `init` — create config from example
- `wizard` — interactive setup
- `setup-project` — initialize Quartz workspace if needed
- `doctor` — dependency/env/path checks

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill advertises commands that use environment variables for Cloudflare tokens and local .env loading, but it does not declare any explicit tool scope or permissions boundaries. In an agent setting, missing scope metadata can cause overbroad execution or secret access assumptions, making it harder to constrain what the skill may read from the environment.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Referencing npx quartz without pinning a version introduces supply-chain risk because the executed package can change over time or resolve unexpectedly from the registry. That can lead to unreviewed code execution during build/setup, especially dangerous in a skill that also handles local files and deployment credentials.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

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.

Content

Scanner excerpt · SKILL.md (reported line 63)May include surrounding context.

md
## Cloudflare API token setup (recommended)

Create a Cloudflare API token with at least:
- **Account → Cloudflare Pages:Edit**
- (Optional) **Zone → DNS:Edit** if you want DNS automation elsewhere

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

The script executes npx quartz create without pinning a specific package version. This allows the latest package (or a compromised package release) to be fetched and executed at runtime, creating a supply-chain execution risk on the operator's machine.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The fallback bootstrap clones a remote GitHub repository and runs npm i, which executes untrusted third-party code and install scripts on the local machine. This is a significant supply-chain risk, especially because it occurs automatically during setup and is not pinned to a specific commit or release.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The build step runs npx quartz build without pinning the package version used for execution. If Quartz is not already locally installed as a locked dependency, npx may resolve and execute an unexpected or malicious version, which is particularly risky because it processes local vault content and runs on the user's workstation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The middleware generator embeds the basic-auth username and password directly into _middleware.js, writing secrets into source files in the workspace. This increases the chance of accidental disclosure through source control, backups, logs, or later publication of the workspace contents.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The deployment step invokes npx wrangler pages deploy without pinning Wrangler to a specific trusted version. Because this command runs with Cloudflare API credentials in the environment, a malicious or compromised package version could abuse those credentials or alter deployment behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes publishing selected markdown from a vault to a static site and deploying it, but this function additionally reads the user's Obsidian desktop configuration under the home directory to enumerate vault paths. That host-environment inspection is not necessary to perform publishing itself; it is only a convenience for setup and expands local access beyond the stated core purpose.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
bin/publishmd-cf.js:54