Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions .github/workflows/poll-nvd-cves.yml
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ jobs:
(if ($blob | test("github\\.com/openclaw/openclaw|\\bopenclaw\\b|\\bclawdbot\\b|\\bmoltbot\\b")) then ["openclaw@*"] else [] end)
+ (if ($blob | test("github\\.com/qwibitai/nanoclaw|\\bnanoclaw\\b|whatsapp-bot|\\bbaileys\\b")) then ["nanoclaw@*"] else [] end)
+ (if ($blob | test("github\\.com/softwarepub/hermes|cpe:2\\.3:a:software-metadata\\.pub:hermes|\\bhermes workflow\\b|software publication with rich metadata")) then ["hermes@*"] else [] end)
+ (if ($blob | test("github\\.com/[^/]+/picoclaw|\\bpicoclaw\\b|cpe:2\\.3:[aho]:[^:]*:picoclaw(?::|$)")) then ["picoclaw@*"] else [] end)
)
);

Expand All @@ -414,14 +415,15 @@ jobs:
[
(if ($targets | map(strings | ascii_downcase | select(startswith("openclaw@") or test("^cpe:2\\.3:[aho]:openclaw:openclaw(?::|$)"))) | length > 0) then "openclaw" else empty end),
(if ($targets | map(strings | ascii_downcase | select(startswith("nanoclaw@") or test("^cpe:2\\.3:[aho]:[^:]*:nanoclaw(?::|$)"))) | length > 0) then "nanoclaw" else empty end),
(if ($targets | map(strings | ascii_downcase | select(startswith("hermes@") or test("^cpe:2\\.3:[aho]:software-metadata\\.pub:hermes(?::|$)"))) | length > 0) then "hermes" else empty end)
(if ($targets | map(strings | ascii_downcase | select(startswith("hermes@") or test("^cpe:2\\.3:[aho]:software-metadata\\.pub:hermes(?::|$)"))) | length > 0) then "hermes" else empty end),
(if ($targets | map(strings | ascii_downcase | select(startswith("picoclaw@") or test("^cpe:2\\.3:[aho]:[^:]*:picoclaw(?::|$)"))) | length > 0) then "picoclaw" else empty end)
]
);

def normalized_affected:
(
matched_targets
| if length == 0 then ["openclaw@*", "nanoclaw@*", "hermes@*"] else . end
| if length == 0 then ["openclaw@*", "nanoclaw@*", "hermes@*", "picoclaw@*"] else . end
);

def normalized_platforms:
Expand All @@ -432,7 +434,7 @@ jobs:
else
matched_targets as $targets
| platforms_from_targets($targets) as $from_targets
| if ($from_targets | length) > 0 then $from_targets else ["openclaw", "nanoclaw", "hermes"] end
| if ($from_targets | length) > 0 then $from_targets else ["openclaw", "nanoclaw", "hermes", "picoclaw"] end
end
);

Expand Down Expand Up @@ -639,6 +641,7 @@ jobs:
(if ($blob | test("github\\.com/openclaw/openclaw|\\bopenclaw\\b|\\bclawdbot\\b|\\bmoltbot\\b")) then ["openclaw@*"] else [] end)
+ (if ($blob | test("github\\.com/qwibitai/nanoclaw|\\bnanoclaw\\b|whatsapp-bot|\\bbaileys\\b")) then ["nanoclaw@*"] else [] end)
+ (if ($blob | test("github\\.com/softwarepub/hermes|cpe:2\\.3:a:software-metadata\\.pub:hermes|\\bhermes workflow\\b|software publication with rich metadata")) then ["hermes@*"] else [] end)
+ (if ($blob | test("github\\.com/[^/]+/picoclaw|\\bpicoclaw\\b|cpe:2\\.3:[aho]:[^:]*:picoclaw(?::|$)")) then ["picoclaw@*"] else [] end)
)
);

Expand All @@ -654,14 +657,15 @@ jobs:
[
(if ($targets | map(strings | ascii_downcase | select(startswith("openclaw@") or test("^cpe:2\\.3:[aho]:openclaw:openclaw(?::|$)"))) | length > 0) then "openclaw" else empty end),
(if ($targets | map(strings | ascii_downcase | select(startswith("nanoclaw@") or test("^cpe:2\\.3:[aho]:[^:]*:nanoclaw(?::|$)"))) | length > 0) then "nanoclaw" else empty end),
(if ($targets | map(strings | ascii_downcase | select(startswith("hermes@") or test("^cpe:2\\.3:[aho]:software-metadata\\.pub:hermes(?::|$)"))) | length > 0) then "hermes" else empty end)
(if ($targets | map(strings | ascii_downcase | select(startswith("hermes@") or test("^cpe:2\\.3:[aho]:software-metadata\\.pub:hermes(?::|$)"))) | length > 0) then "hermes" else empty end),
(if ($targets | map(strings | ascii_downcase | select(startswith("picoclaw@") or test("^cpe:2\\.3:[aho]:[^:]*:picoclaw(?::|$)"))) | length > 0) then "picoclaw" else empty end)
]
);

def normalized_affected:
(
matched_targets
| if length == 0 then ["openclaw@*", "nanoclaw@*", "hermes@*"] else . end
| if length == 0 then ["openclaw@*", "nanoclaw@*", "hermes@*", "picoclaw@*"] else . end
);

def normalized_platforms:
Expand All @@ -672,7 +676,7 @@ jobs:
else
matched_targets as $targets
| platforms_from_targets($targets) as $from_targets
| if ($from_targets | length) > 0 then $from_targets else ["openclaw", "nanoclaw", "hermes"] end
| if ($from_targets | length) > 0 then $from_targets else ["openclaw", "nanoclaw", "hermes", "picoclaw"] end
end
);

Expand Down
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ ClawSec is a **complete security skill suite for AI agent platforms**. It provid
- **OpenClaw** (MoltBot, Clawdbot, and clones) - Full suite with skill installer, file integrity protection, and security audits
- **NanoClaw** - Containerized WhatsApp bot security with MCP tools for advisory monitoring, signature verification, and file integrity
- **Hermes** - Hermes-native security skills for signed advisory feed verification, advisory-aware guarded verification, deterministic attestation generation, fail-closed verification, and baseline drift detection
- **Picoclaw** - Lightweight AI gateway security posture checks with advisory awareness, config drift detection, release-artifact verification, and an optional separate self-pen-testing package

### Skill Feature Matrix

Expand All @@ -54,6 +55,8 @@ ClawSec is a **complete security skill suite for AI agent platforms**. It provid
| clawtributor | OpenClaw | Yes | No | No | No |
| hermes-attestation-guardian | Hermes | Yes (signed advisory feed verification) | Yes | No | Limited (advisory preflight gating only; no artifact signature/provenance install verification) |
| openclaw-audit-watchdog | OpenClaw | No | No | Yes | No |
| picoclaw-security-guardian | Picoclaw | Yes | Yes | No | Yes |
| picoclaw-self-pen-testing | Picoclaw | No | No | Yes | No |
| soul-guardian | OpenClaw | No | Yes | No | No |

### Core Capabilities
Expand Down Expand Up @@ -135,12 +138,16 @@ Troubleshooting: if you see directories such as `~/.openclaw/workspace/$HOME/...
Detailed platform and suite docs live in the wiki modules:
- NanoClaw: [wiki/modules/nanoclaw-integration.md](wiki/modules/nanoclaw-integration.md)
- Hermes: [wiki/modules/hermes-attestation-guardian.md](wiki/modules/hermes-attestation-guardian.md)
- Picoclaw: [wiki/modules/picoclaw-security-guardian.md](wiki/modules/picoclaw-security-guardian.md)
- Picoclaw self-pen-testing: [wiki/modules/picoclaw-self-pen-testing.md](wiki/modules/picoclaw-self-pen-testing.md)
- ClawSec Suite (OpenClaw): [wiki/modules/clawsec-suite.md](wiki/modules/clawsec-suite.md)
- CI/CD pipelines: [wiki/modules/automation-release.md](wiki/modules/automation-release.md)

Quick install links:
- NanoClaw install: [skills/clawsec-nanoclaw/INSTALL.md](skills/clawsec-nanoclaw/INSTALL.md)
- Hermes skill package: `skills/hermes-attestation-guardian/`
- Picoclaw guardian package: `skills/picoclaw-security-guardian/`
- Picoclaw self-pen-testing package: `skills/picoclaw-self-pen-testing/`
- Suite package: `skills/clawsec-suite/`

---
Expand All @@ -164,6 +171,7 @@ Compatibility mirror (legacy): `https://clawsec.prompt.security/releases/latest/
The feed polls CVEs related to:
- **OpenClaw Platform**: `OpenClaw`, `clawdbot`, `Moltbot`
- **NanoClaw Platform**: `NanoClaw`, `WhatsApp-bot`, `baileys`
- **Picoclaw Platform**: `Picoclaw`, `picoclaw`, lightweight AI gateways, MCP gateway exposure
- Prompt injection patterns
- Agent security vulnerabilities

Expand Down Expand Up @@ -219,7 +227,9 @@ This feature helps agents prioritize vulnerabilities that pose immediate threats
**Platform values:**
- `"openclaw"` - OpenClaw/Clawdbot/MoltBot only
- `"nanoclaw"` - NanoClaw only
- `["openclaw", "nanoclaw"]` - Both platforms
- `"hermes"` - Hermes only
- `"picoclaw"` - Picoclaw only
- `["openclaw", "nanoclaw", "hermes", "picoclaw"]` - All core platforms
Comment on lines 228 to +232
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

README advertises picoclaw as a core platform but CorePlatformSlug, isCorePlatformSlug(), and AdvisoryPlatformFilter don't include it, so picoclaw falls through to "other" in FeedSetup.tsx — should we update CORE_PLATFORM_SLUGS and related types/badge mapping to include picoclaw, or remove it from the docs until the contract is ready?

Finding types: Breaking Changes | Severity: 🟠 Medium


Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents:

Resolve the inconsistency between the README and the runtime taxonomy for `picoclaw`: -
Either update the shared core-platform contract — `CORE_PLATFORM_SLUGS`,
`CorePlatformSlug`, `isCorePlatformSlug()`, `AdvisoryPlatformFilter`, and any related
badge/tab mapping in `pages/FeedSetup.tsx` — to include `picoclaw` so it renders as a
first-class tab/filter option. - Or, if that runtime change is out of scope, remove
`picoclaw` from the README's core platform list (lines 231-232) and document it under an
"Other"/non-core category until the UI supports it. Verify against the current code
before applying, and ensure the UI badge descriptor for `picoclaw` matches whichever
path is chosen.

- (empty/missing) - All platforms (backward compatible)

---
Expand Down Expand Up @@ -340,6 +350,8 @@ npm run build
│ ├── clawtributor/ # 🤝 Community reporting skill
│ ├── hermes-attestation-guardian/ # 🛡️ Hermes attestation + drift verification
│ ├── openclaw-audit-watchdog/ # 🔭 Automated audit skill
│ ├── picoclaw-security-guardian/ # 🦐 Picoclaw posture/advisory/drift/supply-chain checks
│ ├── picoclaw-self-pen-testing/ # 🧪 Picoclaw self-pen-testing checks (separate package)
│ └── soul-guardian/ # 👻 File integrity skill
├── utils/
│ ├── package_skill.py # Skill packager utility
Expand Down
3 changes: 2 additions & 1 deletion pages/FeedSetup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const PLATFORM_TABS = [
{ value: 'openclaw', label: 'OpenClaw', active: 'bg-clawd-accent/20 text-clawd-accent border-2 border-clawd-accent', inactive: 'bg-clawd-800 text-gray-400 border border-clawd-700 hover:border-clawd-accent/50' },
{ value: 'nanoclaw', label: 'NanoClaw', active: 'bg-clawd-secondary/20 text-clawd-secondary border-2 border-clawd-secondary', inactive: 'bg-clawd-800 text-gray-400 border border-clawd-700 hover:border-clawd-secondary/50' },
{ value: 'hermes', label: 'Hermes', active: 'bg-emerald-500/20 text-emerald-300 border-2 border-emerald-400', inactive: 'bg-clawd-800 text-gray-400 border border-clawd-700 hover:border-emerald-400/50' },
{ value: 'picoclaw', label: 'Picoclaw', active: 'bg-cyan-500/20 text-cyan-300 border-2 border-cyan-400', inactive: 'bg-clawd-800 text-gray-400 border border-clawd-700 hover:border-cyan-400/50' },
{ value: 'other', label: 'Other', active: 'bg-clawd-600/40 text-gray-100 border-2 border-clawd-500', inactive: 'bg-clawd-800 text-gray-400 border border-clawd-700 hover:border-clawd-500/50' },
Comment on lines 29 to 33
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

PLATFORM_TABS duplicates core platform definitions already in types.ts::CORE_PLATFORM_SLUGS and utils/advisoryPlatforms.ts::PLATFORM_DESCRIPTOR_BY_SLUG, so adding a platform means updating multiple places or it gets omitted—can we derive the tab metadata from the shared descriptor/slug source?

Finding type: Code Dedup and Conventions | Severity: 🟢 Low


Want Baz to fix this for you? Activate Fixer

] as const satisfies ReadonlyArray<FilterTabOption<AdvisoryPlatformFilter>>;

Expand Down Expand Up @@ -157,7 +158,7 @@ export const FeedSetup: React.FC = () => {
<h1 className="text-3xl md:text-4xl text-white">Security Hardening Feed</h1>
<p className="text-gray-400 max-w-2xl mx-auto">
A continuous stream of security advisories from NVD CVE data and staff-approved community reports.
This feed is automatically updated with OpenClaw, NanoClaw, and Hermes-related vulnerabilities and verified security incidents.
This feed is automatically updated with OpenClaw, NanoClaw, Hermes, and Picoclaw-related vulnerabilities and verified security incidents.
</p>
{lastUpdated && (
<p className="text-xs text-gray-500">
Expand Down
8 changes: 5 additions & 3 deletions scripts/feed-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,22 @@ keyword|NanoClaw
keyword|WhatsApp-bot
keyword|baileys
keyword|hermes workflow
keyword|Picoclaw
virtualMatchString|cpe:2.3:a:software-metadata.pub:hermes
virtualMatchString|cpe:2.3:a:picoclaw:picoclaw
EOF
}

nvd_keyword_pattern() {
echo 'OpenClaw|clawdbot|Moltbot|openclaw|NanoClaw|nanoclaw|WhatsApp-bot|baileys|HERMES workflow|software publication with rich metadata'
echo 'OpenClaw|clawdbot|Moltbot|openclaw|NanoClaw|nanoclaw|WhatsApp-bot|baileys|HERMES workflow|software publication with rich metadata|Picoclaw|picoclaw'
}

nvd_github_ref_pattern() {
echo 'github\.com/openclaw/openclaw|github\.com/qwibitai/nanoclaw|github\.com/softwarepub/hermes'
echo 'github\.com/openclaw/openclaw|github\.com/qwibitai/nanoclaw|github\.com/softwarepub/hermes|github\.com/[^/]+/picoclaw'
}

nvd_cpe_pattern() {
echo 'cpe:2\.3:a:software-metadata\.pub:hermes(?::|$)'
echo 'cpe:2\.3:a:software-metadata\.pub:hermes(?::|$)|cpe:2\.3:[aho]:[^:]*:picoclaw(?::|$)'
}

nvd_query_slug() {
Expand Down
10 changes: 6 additions & 4 deletions scripts/populate-local-feed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ jq --slurpfile existing "$TEMP_DIR/existing_ids.json" '
(if ($blob | test("github\\.com/openclaw/openclaw|\\bopenclaw\\b|\\bclawdbot\\b|\\bmoltbot\\b")) then ["openclaw@*"] else [] end)
+ (if ($blob | test("github\\.com/qwibitai/nanoclaw|\\bnanoclaw\\b|whatsapp-bot|\\bbaileys\\b")) then ["nanoclaw@*"] else [] end)
+ (if ($blob | test("github\\.com/softwarepub/hermes|cpe:2\\.3:a:software-metadata\\.pub:hermes|\\bhermes workflow\\b|software publication with rich metadata")) then ["hermes@*"] else [] end)
+ (if ($blob | test("github\\.com/[^/]+/picoclaw|\\bpicoclaw\\b|cpe:2\\.3:[aho]:[^:]*:picoclaw(?::|$)")) then ["picoclaw@*"] else [] end)
)
);

Expand All @@ -286,14 +287,15 @@ jq --slurpfile existing "$TEMP_DIR/existing_ids.json" '
[
(if ($targets | map(strings | ascii_downcase | select(startswith("openclaw@") or test("^cpe:2\\.3:[aho]:openclaw:openclaw(?::|$)"))) | length > 0) then "openclaw" else empty end),
(if ($targets | map(strings | ascii_downcase | select(startswith("nanoclaw@") or test("^cpe:2\\.3:[aho]:[^:]*:nanoclaw(?::|$)"))) | length > 0) then "nanoclaw" else empty end),
(if ($targets | map(strings | ascii_downcase | select(startswith("hermes@") or test("^cpe:2\\.3:[aho]:software-metadata\\.pub:hermes(?::|$)"))) | length > 0) then "hermes" else empty end)
(if ($targets | map(strings | ascii_downcase | select(startswith("hermes@") or test("^cpe:2\\.3:[aho]:software-metadata\\.pub:hermes(?::|$)"))) | length > 0) then "hermes" else empty end),
(if ($targets | map(strings | ascii_downcase | select(startswith("picoclaw@") or test("^cpe:2\\.3:[aho]:[^:]*:picoclaw(?::|$)"))) | length > 0) then "picoclaw" else empty end)
]
);

def normalized_affected:
(
matched_targets
| if length == 0 then ["openclaw@*", "nanoclaw@*", "hermes@*"] else . end
| if length == 0 then ["openclaw@*", "nanoclaw@*", "hermes@*", "picoclaw@*"] else . end
);

def normalized_platforms:
Expand All @@ -304,7 +306,7 @@ jq --slurpfile existing "$TEMP_DIR/existing_ids.json" '
else
matched_targets as $targets
| platforms_from_targets($targets) as $from_targets
| if ($from_targets | length) > 0 then $from_targets else ["openclaw", "nanoclaw", "hermes"] end
| if ($from_targets | length) > 0 then $from_targets else ["openclaw", "nanoclaw", "hermes", "picoclaw"] end
end
);

Expand Down Expand Up @@ -406,7 +408,7 @@ else
jq -n --slurpfile advisories "$TEMP_DIR/new_advisories.json" --arg now "$NOW" '{
version: "1.0.0",
updated: $now,
description: "Community-driven security advisory feed for ClawSec. Automatically updated with OpenClaw, NanoClaw, and Hermes-related CVEs from NVD.",
description: "Community-driven security advisory feed for ClawSec. Automatically updated with OpenClaw, NanoClaw, Hermes, and Picoclaw-related CVEs from NVD.",
advisories: (($advisories[0] // []) | sort_by(.published) | reverse)
}' > "$TEMP_DIR/updated_feed.json"
fi
Expand Down
11 changes: 11 additions & 0 deletions skills/picoclaw-security-guardian/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Changelog

## [0.0.1] - 2026-04-26

### Added
- Initial Picoclaw-specific ClawSec skill package for advisory awareness, deterministic profile generation, drift detection, and supply-chain verification.
- Picoclaw-native Docker pre-release install regression harness using `find_skills` / `install_skill` and skill-loader validation.

### Changed
- Split optional posture-review checks into separate `picoclaw-self-pen-testing` package so this package remains the core public guardian lane.
- Updated metadata/docs/regression expectations to keep this package focused on advisory, drift, and supply-chain checks.
51 changes: 51 additions & 0 deletions skills/picoclaw-security-guardian/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# picoclaw-security-guardian

Picoclaw security posture skill for ClawSec.

Status: implemented (v0.0.1), Picoclaw-specific.

Detailed architecture/operator docs: `wiki/modules/picoclaw-security-guardian.md`.

## Support matrix mapping

| Skill name | supported platform | security feed | config drift | agent posture-review lane | chain of supply verification |
|---|---|---|---|---|---|
| picoclaw-security-guardian | Picoclaw | Yes | Yes | Separate package | Yes |

## Capabilities

- Picoclaw-aware advisory filtering from a verified ClawSec feed/cache.
- Deterministic local posture profile generation for configs, gateway exposure, tools, MCP, credentials/security files, and release artifacts.
- Baseline drift comparison with critical/high/medium/low/info findings.
- Supply-chain verification for release artifacts using SHA-256 manifests plus required Ed25519 detached signatures for passing provenance verdicts.

## Quickstart

```bash
node scripts/generate_profile.mjs --output ~/.picoclaw/security/clawsec/current-profile.json
node scripts/check_drift.mjs --baseline ~/.picoclaw/security/clawsec/baseline-profile.json --current ~/.picoclaw/security/clawsec/current-profile.json
node scripts/verify_supply_chain.mjs --artifact ./picoclaw --checksums ./checksums.json --signature ./checksums.json.sig --public-key ./feed-signing-public.pem
node scripts/check_advisories.mjs --feed ~/.picoclaw/security/clawsec/feed.json --state ~/.picoclaw/security/clawsec/feed-verification-state.json
```

All scripts are read-only except profile/report outputs explicitly requested by `--output`.

## Tests

```bash
node test/profile.test.mjs
node test/drift.test.mjs
node test/supply_chain.test.mjs
bash -n test/picoclaw_security_guardian_sandbox_regression.sh
```

## Pre-release install regression

Run this before cutting v0.0.1 release artifacts:

```bash
test/picoclaw_security_guardian_sandbox_regression.sh
```

It uses Docker to publish the skill through a local ClawHub-compatible registry, installs it with Picoclaw's own `find_skills` / `install_skill` flow into an isolated Picoclaw workspace, confirms Picoclaw's skill loader can list/load it, then verifies the installed copy's profile, drift, advisory, and supply-chain paths.

Loading
Loading