Skip to content
Merged
133 changes: 133 additions & 0 deletions skills/clawsec-clawhub-checker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# ClawSec ClawHub Checker

A ClawSec suite skill that enhances the guarded skill installer with ClawHub reputation checks and VirusTotal Code Insight integration.

## Purpose

Adds a second layer of security to skill installation by:
1. Checking ClawHub's VirusTotal Code Insight reputation scores
2. Analyzing skill age, author reputation, and download statistics
3. Requiring double confirmation for suspicious skills
4. Integrating with existing ClawSec advisory checks

## Architecture

```
clawsec-suite (base)
└── clawsec-clawhub-checker (enhancement)
├── enhanced_guarded_install.mjs - Main enhanced installer
├── check_clawhub_reputation.mjs - Reputation checking logic
├── setup_reputation_hook.mjs - Integration script
└── hooks/ - Enhanced advisory guardian hook
```

## Installation

```bash
# First install the base suite
npx clawhub install clawsec-suite

# Then install the checker
npx clawhub install clawsec-clawhub-checker

# Run setup to integrate with existing suite
node scripts/setup_reputation_hook.mjs

# Restart OpenClaw gateway
openclaw gateway restart
```

Setup installs these scripts into `clawsec-suite/scripts`:
- `enhanced_guarded_install.mjs`
- `guarded_skill_install_wrapper.mjs` (drop-in wrapper)
- `check_clawhub_reputation.mjs`

The original `guarded_skill_install.mjs` remains unchanged.

## Usage

### Enhanced Guarded Installer

```bash
# Basic usage via wrapper (includes reputation checks)
node scripts/guarded_skill_install_wrapper.mjs --skill some-skill --version 1.0.0

# Direct usage (enhanced script)
node scripts/enhanced_guarded_install.mjs --skill some-skill --version 1.0.0

# With reputation confirmation override
node scripts/guarded_skill_install_wrapper.mjs --skill suspicious-skill --version 1.0.0 --confirm-reputation

# Adjust reputation threshold (default: 70)
node scripts/guarded_skill_install_wrapper.mjs --skill some-skill --reputation-threshold 80
```

### Reputation Check Only

```bash
# Check reputation without installation
node scripts/check_clawhub_reputation.mjs some-skill 1.0.0 70
```

## Exit Codes

- `0` - Safe to install
- `42` - Advisory match found (requires `--confirm-advisory`)
- `43` - Reputation warning (requires `--confirm-reputation`) - **NEW**
- `1` - Error

## Reputation Signals Checked

1. **VirusTotal Code Insight** - Malicious code patterns
2. **Skill Age** - New skills (<7 days) are riskier
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README.md lists CLAWHUB_ALLOW_SUSPICIOUS as a supported environment variable, but none of the scripts read it. Either implement the behavior or remove it from the docs to avoid misleading configuration guidance.

Suggested change
2. **Skill Age** - New skills (<7 days) are riskier

Copilot uses AI. Check for mistakes.
3. **Author Reputation** - Number of published skills
4. **Update Frequency** - Stale skills (>90 days)
5. **Download Statistics** - Low download counts
6. **Version Existence** - Specified version availability

## Configuration

Environment variables:
- `CLAWHUB_REPUTATION_THRESHOLD` - Minimum score (0-100, default: 70)

## Integration Points

1. **Enhanced `guarded_skill_install.mjs`** - Wraps original with reputation checks
via `guarded_skill_install_wrapper.mjs` and `enhanced_guarded_install.mjs`
2. **Updated advisory guardian hook** - Adds reputation warnings to alerts
3. **Catalog entry in clawsec-suite** - Listed as available enhancement

## Development

### Files

- `SKILL.md` - Main documentation
- `skill.json` - Skill metadata and SBOM
- `scripts/enhanced_guarded_install.mjs` - Enhanced installer
- `scripts/check_clawhub_reputation.mjs` - Reputation logic
- `scripts/setup_reputation_hook.mjs` - Integration script
- `hooks/clawsec-advisory-guardian/lib/reputation.mjs` - Hook module

### Testing

```bash
# Test reputation check
node scripts/check_clawhub_reputation.mjs clawsec-suite

# Test enhanced installer (dry run)
node scripts/enhanced_guarded_install.mjs --skill test-skill --dry-run

# Test setup
node scripts/setup_reputation_hook.mjs
```

## Security Considerations

- Reputation checks are **heuristic**, not definitive
- **False positives** possible with legitimate novel skills
- Always **review skill code** before overriding warnings
- This is **defense-in-depth**, not replacement for advisory feeds

## License

MIT - Part of the ClawSec security suite
149 changes: 149 additions & 0 deletions skills/clawsec-clawhub-checker/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
name: clawsec-clawhub-checker
version: 0.0.1
description: ClawHub reputation checker for ClawSec suite. Enhances guarded skill installer with VirusTotal Code Insight reputation scores and additional safety checks.
homepage: https://clawsec.prompt.security
clawdis:
emoji: "🛡️"
requires:
bins: [clawhub, curl, jq]
depends_on: [clawsec-suite]
---

# ClawSec ClawHub Checker

Enhances the ClawSec suite's guarded skill installer with ClawHub reputation checks. Adds a second layer of security by checking VirusTotal Code Insight scores and other reputation signals before allowing skill installation.

## What It Does

1. **Wraps `clawhub install`** - Intercepts skill installation requests
2. **Checks VirusTotal reputation** - Uses ClawHub's built-in VirusTotal Code Insight
3. **Adds double confirmation** - For suspicious skills (reputation score below threshold)
4. **Integrates with advisory feed** - Works alongside existing clawsec-suite advisories
5. **Provides detailed reports** - Shows why a skill is flagged as suspicious

## Installation

This skill must be installed **after** `clawsec-suite`:

```bash
# First install the suite
npx clawhub@latest install clawsec-suite

# Then install the checker
npx clawhub@latest install clawsec-clawhub-checker

# Run the setup script to integrate with clawsec-suite
node ~/.openclaw/skills/clawsec-clawhub-checker/scripts/setup_reputation_hook.mjs

# Restart OpenClaw gateway for changes to take effect
openclaw gateway restart
```

After setup, the checker adds `enhanced_guarded_install.mjs` and
`guarded_skill_install_wrapper.mjs` under `clawsec-suite/scripts` and updates the advisory
guardian hook. The original `guarded_skill_install.mjs` is not replaced.

## How It Works

### Enhanced Guarded Installer

After setup, run the wrapper (drop-in path) or the enhanced script directly:
```bash
# Recommended drop-in wrapper
node scripts/guarded_skill_install_wrapper.mjs --skill some-skill --version 1.0.0

# Or call the enhanced script directly
node scripts/enhanced_guarded_install.mjs --skill some-skill --version 1.0.0
```

The enhanced flow:
1. **Advisory check** (existing) - Checks clawsec advisory feed
2. **Reputation check** (new) - Queries ClawHub for VirusTotal scores
3. **Risk assessment** - Combines advisory + reputation signals
4. **Double confirmation** - If risky, requires explicit `--confirm-reputation`

### Reputation Signals Checked

1. **VirusTotal Code Insight** - Malicious code patterns, external dependencies (Docker usage, network calls, eval usage, crypto keys)
2. **Skill age & updates** - New skills vs established ones
3. **Author reputation** - Other skills by same author
4. **Download statistics** - Popularity signals

### Exit Codes

- `0` - Safe to install (no advisories, good reputation)
- `42` - Advisory match found (existing behavior)
- `43` - Reputation warning (new - requires `--confirm-reputation`)
- `1` - Error

Comment on lines +78 to +79
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section documents CLAWHUB_ALLOW_SUSPICIOUS and CLAWHUB_VIRUSTOTAL_API_KEY, but there is no implementation in this skill that reads or applies these environment variables. Either implement them or remove/clarify them so users don’t assume the behavior exists.

Suggested change
- `1` - Error
- `CLAWHUB_ALLOW_SUSPICIOUS` - Reserved for future use; not currently read by this skill. Intended to allow installation of suspicious skills without confirmation.
- `CLAWHUB_VIRUSTOTAL_API_KEY` - Reserved for future use; not currently read by this skill. Intended for using your own VirusTotal API key for deeper scans.

Copilot uses AI. Check for mistakes.
## Configuration

Environment variables:
- `CLAWHUB_REPUTATION_THRESHOLD` - Minimum reputation score (0-100, default: 70)

## Integration with Existing Suite

The checker enhances but doesn't replace existing security:
- **Advisory feed still primary** - Known malicious skills blocked first
- **Reputation is secondary** - Unknown/suspicious skills get extra scrutiny
- **Double confirmation preserved** - Both layers require explicit user approval

## Example Usage

```bash
# Try to install a skill
node scripts/guarded_skill_install_wrapper.mjs --skill suspicious-skill --version 1.0.0

# Output might show:
# WARNING: Skill "suspicious-skill" has low reputation score (45/100)
# - Flagged by VirusTotal Code Insight: crypto keys, external APIs, eval usage
# - Author has no other published skills
# - Skill is less than 7 days old
#
# To install despite reputation warning, run:
# node scripts/guarded_skill_install_wrapper.mjs --skill suspicious-skill --version 1.0.0 --confirm-reputation

# Install with confirmation
node scripts/guarded_skill_install_wrapper.mjs --skill suspicious-skill --version 1.0.0 --confirm-reputation
```

## Safety Notes

- This is a **defense-in-depth** layer, not a replacement for advisory feeds
- VirusTotal scores are **heuristic**, not definitive
- **False positives possible** - Legitimate skills with novel patterns might be flagged
- Always **review skill code** before installing with `--confirm-reputation`

## Current Limitations

### Missing OpenClaw Internal Check Data
ClawHub shows two security badges on skill pages:
1. **VirusTotal Code Insight** - ✅ Our checker catches these flags
2. **OpenClaw internal check** - ❌ Not exposed via API (only on website)

Example from `clawsec-suite` page:
- VirusTotal: "Benign" ✓
- OpenClaw internal check: "The package is internally consistent with a feed-monitoring / advisory-guardian purpose, but a few operational details and optional bypasses deserve attention before installing."

**Our checker cannot access OpenClaw internal check warnings** as they're not exposed via `clawhub` CLI or API.

### Recommendation for ClawHub
To enable complete reputation checking, ClawHub should expose internal check results via:
- `clawhub inspect --json` endpoint
- Additional API field for security tools
- Or include in `clawhub install` warning output

### Workaround
Our heuristic checks (skill age, author reputation, downloads, updates) provide similar risk assessment but miss specific operational warnings about bypasses, missing signatures, etc. Always check the ClawHub website for complete security assessment.

## Development

To modify the reputation checking logic, edit:
- `scripts/enhanced_guarded_install.mjs` - Main enhanced installer
- `scripts/check_clawhub_reputation.mjs` - Reputation checking logic
- `hooks/clawsec-advisory-guardian/lib/reputation.mjs` - Hook integration

## License

MIT - Part of the ClawSec security suite
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import path from "node:path";

/**
* Check reputation for a skill
* @param {string} skillName - Skill name
* @param {string} version - Skill version
* @returns {Promise<{safe: boolean, score: number, warnings: string[]}>}
*/
export async function checkReputation(skillName, version) {
const result = {
safe: true,
score: 100,
warnings: [],
};

try {
// Try to get skill slug from directory name or skill.json
// For now, use skillName as slug (simplified)
const skillSlug = skillName.toLowerCase().replace(/[^a-z0-9-]/g, '-');

// Run the reputation check script
// Current file is at: .../hooks/clawsec-advisory-guardian/lib/reputation.mjs
// We need to go up 3 levels to get to the skill root directory
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const checkerDir = path.resolve(__dirname, '../../..');

const reputationCheck = spawnSync(
"node",
[
`${checkerDir}/scripts/check_clawhub_reputation.mjs`,
skillSlug,
Comment on lines +29 to +33
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This spawnSync call runs ${checkerDir}/scripts/check_clawhub_reputation.mjs where checkerDir is derived from the current file location. After setup_reputation_hook.mjs copies this module into clawsec-suite/hooks/..., checkerDir will resolve to the suite root (which does not contain that script), so the hook’s reputation check will fail. Make the script location resolution independent of the file’s location, or ensure the setup step copies the checker script into the suite.

Copilot uses AI. Check for mistakes.
version || "",
"70" // Default threshold
],
{ encoding: "utf-8", cwd: checkerDir }
);

if (reputationCheck.status === 0) {
try {
const repResult = JSON.parse(reputationCheck.stdout);
result.safe = repResult.safe;
result.score = repResult.score;
result.warnings = repResult.warnings;
} catch (parseError) {
result.warnings.push(`Failed to parse reputation result: ${parseError.message}`);
result.score = 60;
result.safe = result.score >= 70;
}
} else if (reputationCheck.status === 43) {
// Reputation warning exit code
try {
const repResult = JSON.parse(reputationCheck.stdout);
result.safe = false;
result.score = repResult.score;
result.warnings = repResult.warnings;
} catch {
result.safe = false;
result.score = 50;
result.warnings.push("Skill flagged by reputation check");
}
} else {
// Error running check
result.warnings.push(`Reputation check failed: ${reputationCheck.stderr || 'Unknown error'}`);
result.score = 60;
result.safe = result.score >= 70;
}
} catch (error) {
result.warnings.push(`Reputation check error: ${error.message}`);
result.score = 50;
result.safe = result.score >= 70;
}

return result;
}

/**
* Format reputation warning for alert messages
* @param {{score: number, warnings: string[]}} reputationInfo
* @returns {string}
*/
export function formatReputationWarning(reputationInfo) {
if (!reputationInfo || reputationInfo.score >= 70) return "";

const lines = [
`\n⚠️ **REPUTATION WARNING** (Score: ${reputationInfo.score}/100)`,
];

if (reputationInfo.warnings.length > 0) {
lines.push("");
reputationInfo.warnings.forEach(w => lines.push(`• ${w}`));
}

lines.push("");
lines.push("This skill has low reputation score. Review carefully before installation.");

return lines.join("\n");
}
Loading