Back to skill

Security audit

Skillstore

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says, but it can install unverified GitHub repositories into the live skills folder and can write files outside that folder through unsanitized skill names.

Review this skill before installing. It is not clearly malicious, but only use it if you are comfortable with it sending search text to GitHub, cloning third-party repositories into your OpenClaw skills directory, and creating local files. Avoid installing search results from unknown GitHub owners, and avoid using create/new names that include slashes, dots, or path-like text.

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 (2)

T08 · Insecure Dependencies

Warning
Location
main.js:187
Finding

Unverified Third-Party Skill Installation from GitHub

Content
View full analysis

Vulnerability Details

File Location: main.js:187, main.js:265-294
Vulnerability Type: Untrusted and mutable supply-chain component installation
Risk Level: Medium

Vulnerable Code

js
const results = await httpGet(
  `https://api.github.com/search/repositories?q=openclaw+${encodeURIComponent(query)}+in:name,description&per_page=15`
);
js
// Install from GitHub
async function installFromGitHub(repo, name) {
  log(`\nInstalling ${name} from GitHub...`, 'cyan');
  
  const skillsDir = path.join(__dirname, '..');
  const targetDir = path.join(skillsDir, name);
  
  if (fs.existsSync(targetDir)) {
    log(`Skill "${name}" already exists`, 'yellow');
    return false;
  }
  
  const cmd = `git clone https://github.com/${repo}.git "${targetDir}"`;
  
  return new Promise((resolve) => {
    exec(cmd, (error) => {
      if (error) {
        err(`Failed to install: ${error.message}`);
        resolve(false);
        return;
      }
      
      log(`Installed to ${targetDir}`, 'green');
      
      const config = loadConfig();
      config.installed.push({ name, repo, installedAt: new Date().toISOString() });
      saveConfig(config);
      
      resolve(true);
    });
  });
}

Technical Analysis

GitHub repositories are discovered through a public keyword search and can be published by arbitrary accounts. The selected repository is cloned directly into the active skills directory without:

  • A trusted-publisher or repository allowlist
  • Commit pinning
  • Cryptographic signatures or checksum verification
  • Manifest validation
  • Content scanning
  • A quarantine or review stage
  • Clear trust information about the repository owner

The matching algorithm evaluates names and descriptions for relevance, but relevance is not a security or authenticity control. An attacker can create a repository whose metadata closely matches co ...[truncated 1787 chars]

Remediation
View remediation

Remediation Suggestions

  1. Restrict installations to an approved registry or an explicit allowlist of trusted GitHub owners and repositories.
  2. Resolve and pin every installation to an immutable commit hash rather than cloning a mutable default branch.
  3. Verify a cryptographically signed manifest or trusted checksum before placing files in the skills directory.
  4. Clone repositories into a temporary quarantine directory first.
  5. Validate the repository structure and scan scripts, symbolic links, executable files, and skill instructions before activation.
  6. Display the repository owner, immutable commit, creation age, trust status, and source URL, then require explicit confirmation.
  7. Separate installation from activation so downloaded code cannot become available to the agent until review succeeds.
  8. Record the verified commit and integrity metadata in the installation history.
  9. Prefer spawn or execFile with argument arrays over shell-based exec, even though the currently observed repository values originate from GitHub API fields.

T09 · Insecure Skill Coding Practices

Warning
Location
main.js:301
Finding

Directory Traversal Through Unsanitized Skill Names

Content
View full analysis

Vulnerability Details

File Location: main.js:301-305, main.js:398-402, main.js:470-472
Vulnerability Type: Path traversal and creation of files outside the intended skills directory
Risk Level: Medium

Vulnerable Code

js
function createNewSkill(name) {
  log(`\nCreating new skill: ${name}`, 'cyan');
  
  const skillsDir = path.join(__dirname, '..');
  const targetDir = path.join(skillsDir, name);
  
  if (fs.existsSync(targetDir)) {
    err(`Skill "${name}" already exists!`);
    return false;
  }
  
  fs.mkdirSync(targetDir, { recursive: true });
js
for (const [filename, content] of Object.entries(templates)) {
  fs.writeFileSync(path.join(targetDir, filename), content);
}

fs.chmodSync(path.join(targetDir, 'main.js'), '755');
js
if (query.startsWith('create ') || query.startsWith('new ')) {
  const name = query.replace(/^(create|new)\s+/, '');
  createNewSkill(name);
  return;
}

Technical Analysis

The direct create and new commands pass an unsanitized user-supplied name to createNewSkill. The name is combined with the intended skills root using path.join, but the resulting path is not resolved and checked for containment.

A name containing parent-directory components such as ../ can cause targetDir to escape the skills directory. The function then recursively creates that external directory, writes five template files into it, and changes the generated main.js mode to executable.

The check using fs.existsSync(targetDir) prevents writing into a target directory that already exists. This reduces overwrite opportunities, but it does not prevent the creation of a new directory and files at another writable location outside the intended workspace.

The no-results workflow sanitizes a generated name, but the explicit skillstore create <name> and skillstore new <name> paths do not use that sanitization.

...[truncated 1328 chars]

Remediation
View remediation

Remediation Suggestions

  1. Permit only canonical skill slugs using a strict allowlist, for example lowercase letters, digits, and internal hyphens with a bounded length.
  2. Reject names containing /, \, ., .., control characters, or leading and trailing whitespace.
  3. Resolve and validate containment before creating anything:
js
const skillsDir = path.resolve(__dirname, '..');

if (!/^[a-z0-9][a-z0-9-]{0,63}$/.test(name)) {
  throw new Error('Invalid skill name');
}

const targetDir = path.resolve(skillsDir, name);
if (!targetDir.startsWith(skillsDir + path.sep)) {
  throw new Error('Skill path escapes the skills directory');
}
  1. Apply the same validation in every creation path rather than relying on only the no-results workflow to sanitize names.
  2. Use exclusive creation flags and fail closed if any destination file or directory unexpectedly exists.
  3. Where supported, reject symbolic-link path components and verify the real parent directory before writing.
  4. Add tests covering ../, nested traversal, backslashes, absolute-looking names, control characters, empty names, and excessively long names.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill builds and executes a shell command to run git clone against a remote repository selected from search results, pulling untrusted code into the local skills directory. Even though the repository name originates from GitHub metadata, this still introduces a supply-chain risk and relies on shell execution for a high-impact operation.

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

md
# SkillStore - OpenClaw Skill Manager

Search, install, and create OpenClaw skills with intelligent matching.

## Skill Metadata

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly offers installation from GitHub after a search result is selected, but the documentation does not warn users that this action pulls and installs code from a remote repository. That omission can mislead users into treating selection as low-risk discovery rather than code execution or environment modification, increasing the chance of accidental installation of untrusted code.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The instruction to write content when a user says '记住这个' encourages persistent storage of arbitrary user-provided data without any guardrails. In practice, users may provide secrets, tokens, personal data, or other sensitive material, causing unintended retention in markdown files where it may later be exposed, committed, or reused insecurely.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Line L26 states that all formal project documentation must be in English only. This is a language-policy constraint expressed in natural language, and the file does not provide user opt-in, alternatives, or a region-specific justification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module header describes the tool only as an intelligent search manager, but the code also performs remote repository installation and local file creation. This mismatch can mislead users and reviewers about the skill’s true capabilities, reducing informed consent for network access and code-writing behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

Because no manifest is available, remote HTTPS access is not justified by any declared skill purpose. The code queries the GitHub API to search repositories, which is a meaningful capability beyond purely local skill inspection or matching.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · main.js (reported line 187)May include surrounding context.

js
try {
    const results = await httpGet(
      `https://api.github.com/search/repositories?q=openclaw+${encodeURIComponent(query)}+in:name,description&per_page=15`
    );
    
    if (!results.items) return [];

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The tool automatically sends the user's free-form query to GitHub during the search workflow without first warning that input may leave the local environment. User queries can contain sensitive internal project names, hostnames, or operational intent, creating an avoidable privacy leak.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Selecting a numbered result triggers cloning external code into the local skills directory without a final confirmation that names the repository and target path. This makes accidental installation of untrusted code more likely and can lead to supply-chain compromise if a malicious or typosquatted repository is chosen.

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
main.js:282