Back to skill

Security audit

Ghost Theme Builder

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent Ghost theme guidance, but it includes under-scoped commands that can fetch and run mutable third-party code on a user's machine.

Review before installing. The skill is not showing deception or exfiltration, but do not let an agent blindly run the starter-kit, npm, npx, or global install commands. Prefer the minimal bundled theme shape, pin external repositories and packages, review package scripts, and run dependency installs in a constrained project environment. For membership, newsletter, and analytics features, make consent and privacy behavior explicit in the generated theme.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T08 · Insecure Dependencies

Warning
Location
examples/starter-kit.md:3
Finding

Mutable External Starter Kit Is Retrieved and Executed Without Integrity Verification

Content
View full analysis

Vulnerability Details

File Location: examples/starter-kit.md:3-39
Vulnerability Type: Untrusted and unpinned third-party code execution through a starter-kit workflow
Risk Level: Medium

Vulnerable Code

markdown
If you prefer a more opinionated starting point with pre-configured tooling, styles, and templates, use the [Ghost Theme Starter Kit](https://github.com/frontendweb3/ghost-theme-starter-kit) instead of the minimal theme.

Clone it and install dependencies using your preferred package manager:

```bash
git clone https://github.com/frontendweb3/ghost-theme-starter-kit.git my-theme
cd my-theme

npm — default Node.js package manager, comes with Node:

bash
npm install
npm run dev

yarn — faster installs with deterministic lockfile:

bash
yarn install
yarn dev

pnpm — disk-efficient with strict dependency isolation:

bash
pnpm install
pnpm dev
text

The workflow is also made available to new-theme operations by `SKILL.md:35`:

```markdown
- Start new themes from the minimum valid structure or `examples/starter-kit.md`. Add context-specific templates only when their layout differs.

Technical Analysis

The workflow clones the current default branch of a third-party repository without pinning a reviewed commit or verifying its integrity. It then installs dependencies and runs a development command from the retrieved repository.

Package installation can execute dependency lifecycle hooks such as preinstall, install, and postinstall. The subsequent npm run dev, yarn dev, or pnpm dev command executes scripts defined by the remotely retrieved project. Consequently, the effective executable payload can change after this Skill has been reviewed.

The repository is hosted under a third-party account rather than being bundled with the audited Skill or pinned to an immutable revision. A compromise of the repository, main ...[truncated 1577 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer a minimal starter template bundled directly in the audited Skill.
  2. If the external starter kit remains necessary, pin it to a reviewed immutable commit rather than cloning its mutable default branch:
    bash
    git clone --no-checkout https://github.com/frontendweb3/ghost-theme-starter-kit.git my-theme
    cd my-theme
    git checkout --detach EXPECTED_COMMIT_SHA
    
  3. Publish and verify an expected archive checksum or signed commit before using the retrieved files.
  4. Review package.json, package-manager configuration, lockfiles, and all lifecycle and development scripts before execution.
  5. Require a committed lockfile and use the package manager's frozen or clean-install mode.
  6. Perform the initial dependency installation with lifecycle scripts disabled where practical, such as:
    bash
    npm ci --ignore-scripts
    
  7. Run dependency auditing and inspect any package that requires an install script before enabling scripts.
  8. Require explicit user confirmation before cloning third-party code, installing dependencies, or running repository-defined commands.
  9. Execute the workflow in a restricted container or sandbox without unrelated credentials, sensitive mounts, or elevated privileges.

T08 · Insecure Dependencies

Note
Location
docs/gscan.md:13
Finding

GScan Is Installed Globally Without Version Pinning

Content
View full analysis

Vulnerability Details

File Location: docs/gscan.md:13-18
Vulnerability Type: Unpinned global package installation
Risk Level: Low

Vulnerable Code

markdown
### Command line

To use GScan as a command line tool, globally install the `gscan` npm package:

```bash
# Install the npm package
npm install -g gscan
text

### Technical Analysis

The command installs the latest package version resolved under the `gscan` package name and does not pin an audited version or verify package integrity. npm packages may run installation lifecycle scripts. A global installation also places executable files outside the target project and gives a compromised package access to everything available to the invoking package-manager process.

This guidance is broader than necessary for validating one Ghost theme. A project-local, lockfile-controlled validator would reduce both the affected scope and the risk of unexpected version changes.

### Attack Path

1. The npm package, a transitive dependency, package publisher account, or registry delivery path is compromised.
2. A malicious version becomes the version selected by the unpinned `npm install -g gscan` command.
3. A user or agent follows the validation documentation.
4. npm downloads the malicious package and may execute its lifecycle hooks.
5. The package installs a global executable or performs other actions with the invoking user's permissions.
6. The malicious executable may run again when the user invokes `gscan`.

### Impact Assessment

Exploitation could execute arbitrary code with the invoking user's permissions during installation or later validator execution. It could read user-accessible files, environment variables, source code, and package credentials; modify globally installed Node.js tooling; or produce falsified validation results.

The instructions do not require elevated privileges. Therefore, the expected direct scope is the invoking us
...[truncated 206 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin a reviewed GScan version rather than resolving the latest release implicitly.
  2. Install GScan as a project-local development dependency and commit the resulting lockfile:
    bash
    npm install --save-dev --save-exact gscan@REVIEWED_VERSION
    
  3. Use npm ci in automated workflows so the lockfile controls the installed dependency graph.
  4. Invoke the local binary through a package script or the project's node_modules/.bin directory.
  5. Review package provenance, published integrity metadata, lifecycle scripts, and transitive dependency changes before upgrading.
  6. Avoid global installation, especially under an administrator or root account.
  7. Run validation in a restricted environment without unrelated secrets or writable access to sensitive directories.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (28)

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 · docs/content.md (reported line 50)May include surrounding context.

The specific implementation required for making images wider than their container width will depend on your theme’s existing styles. The default Ghost theme Casper uses flexbox to implement layout using the following HTML and CSS:

html
<!-- Output -->

<div class="content">
  <article>

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 · docs/content.md (reported line 363)May include surrounding context.

html
<figure class="kg-card kg-embed-card kg-nft-card">
    <a class="kg-nft-card"> <!-- Link to NFT on OpenSea -->
        <img class="kg-nft-image"> <!-- Image of NFT -->
        <div class="kg-nft-metadata">
            <div class="kg-nft-header">

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 · docs/contexts/author.md (reported line 70)May include surrounding context.

If your theme does have a tag.hbs and author.hbs file all outputting similar post lists to index.hbs you may wish to use a partial to define your post list item, e.g. {{> "loop"}}.

html
<!-- author.hbs -->

<!-- Everything inside the #author tags pulls data from the author -->
{{#author}}

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 · docs/contexts/index-context.md (reported line 43)May include surrounding context.

Example Code

handlebars
<!-- index.hbs -->
<header>
  <h1 class="page-title">{{@site.title}}</h1>
  <h2 class="page-description">{{@site.description}}</h2>

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 · docs/contexts/page.md (reported line 57)May include surrounding context.

{{title}}, {{content}}, {{url}}, {{author}}, {{date}}, {{excerpt}}, {{img_url}}, {{post_class}}], {{tags}}.

html
<!-- page.hbs -->

<!-- Everything inside the #post tags pulls data from the static page -->
{{#post}}

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 · docs/contexts/post.md (reported line 64)May include surrounding context.

html
<!-- post.hbs -->

<!-- Everything inside the #post tags pulls data from the post -->
{{#post}}

<article class="{{post_class}}">

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 · docs/contexts/tag.md (reported line 61)May include surrounding context.

If your theme does have a tag.hbs and author.hbs file all outputting similar post lists to index.hbs you may wish to use a partial to define your post list item, for example: {{> "loop"}}.

html
<!-- tag.hbs -->

<!-- Everything inside of #tag pulls data from the tag -->
{{#tag}}

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 · docs/contexts/post.md (reported line 62)May include surrounding context.

{{content}} is a very simple helper used for outputting post content, when called within a {{#post}}{{/post}} block expression. It makes sure that your HTML gets output correctly.

text
<!-- post.hbs -->

{{#post}}

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 · docs/helpers/data/content.md (reported line 11)May include surrounding context.

{{content}} is a very simple helper used for outputting post content, when called within a {{#post}}{{/post}} block expression. It makes sure that your HTML gets output correctly.

text
<!-- post.hbs -->

{{#post}}

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 · docs/helpers/data/price.md (reported line 39)May include surrounding context.

Passing a currency without a price will output the symbol for that currency:

handlebars
{{price currency="USD"}} <!-- Outputs: $ -->

Example Code

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 · docs/helpers/utility/block.md (reported line 15)May include surrounding context.

Example

handlebars
<!-- default.hbs -->

<body>
    <!-- ... -->

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 · docs/helpers/utility/partials.md (reported line 23)May include surrounding context.

text

```html
<!-- partials/post-card.hbs -->
<article class="post-card.hbs">
  <h2 class="post-card-title">
    <a href="{{url}}">{{title}}</a>

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 · docs/members.md (reported line 165)May include surrounding context.

html
<form data-members-form>
  ...
  <p data-members-error><!-- error message will appear here --></p>
</form>

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 · docs/assets.md (reported line 58)May include surrounding context.

Here’s an example from Ghost default Casper theme implementation:

handlebars
<!-- index.hbs -->

<img class="post-image"
    srcset="{{img_url feature_image size="s"}} 300w,

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 · docs/responsive-images.md (reported line 58)May include surrounding context.

Here’s an example from Ghost default Casper theme implementation:

handlebars
<!-- index.hbs -->

<img class="post-image"
    srcset="{{img_url feature_image size="s"}} 300w,

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

The CONTRIBUTING guide instructs users to run npx ultracite check without pinning a specific package version. npx may fetch and execute the latest package from the registry at runtime, which creates a supply-chain risk if the package is compromised, renamed, or a malicious version is published. In a contributor workflow document, this is a real security issue because readers may copy-paste and execute the command locally.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

This second occurrence again recommends npx ultracite check with no version pinning, exposing contributors to execution of whatever package version the registry serves at the time of use. Because this is in contributor-facing instructions, the unsafe pattern is likely to be followed directly and could enable supply-chain compromise of developer machines or CI environments.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding

The README instructs users to run an npx install command against a remote skill URL without pinning a specific version or immutable artifact. This creates a supply-chain risk: if the upstream package or referenced content changes or is compromised, users may execute unexpected code during installation.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The statement that the skill 'loads automatically when you ask the AI to build, review, or debug a Ghost theme' is broad enough to trigger on common theme-related requests. Overly broad auto-activation increases the chance the skill is invoked in unintended contexts, which can expand prompt/instruction exposure and make prompt-scope or tool-selection mistakes more likely.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

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

md
| Platform | Skill directory |
|---|---|
| **opencode** | `~/.config/opencode/skills/ghost-theme-builder/SKILL.md` |
| **Claude** | `~/.claude/skills/ghost-theme-builder/SKILL.md` |

### Manual reference

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

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

md
| Platform | Skill directory |
|---|---|
| **opencode** | `~/.config/opencode/skills/ghost-theme-builder/SKILL.md` |
| **Claude** | `~/.claude/skills/ghost-theme-builder/SKILL.md` |

### Manual reference

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file documents a signup card that prompts users to enter an email address and submit it via a membership signup form, but the surrounding description only mentions functionality and a marketing disclaimer. There is no warning about collection, transmission, or handling of personal data, which is a user-impacting behavior relevant to privacy.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file describes using custom settings for external integrations and explicitly cites website analytics and Google Analytics as examples, which involve transmitting visitor data to third parties. The section does not include any warning about privacy impact, consent, or data-sharing considerations, so users may enable tracking-related behavior without disclosure.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
60% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · docs/helpers/utility/log.md (reported line 22)May include surrounding context.

{{/foreach}}

text

If you’re developing a theme and running an install [using Ghost-CLI](/install/local/), you must use `NODE_ENV=development ghost run` to make debug output visible in the console.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation explicitly recommends using hidden data-members-newsletter inputs to subscribe users to newsletters without surfacing that choice in the UI. This can enable dark-pattern style consent bypass, causing users to be enrolled in mailing lists they did not knowingly select, with privacy, compliance, and trust implications.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.