[PR #130] [MERGED] VirusTotal Integration on ClawHub #266

Closed
opened 2026-02-15 17:16:34 -05:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/openclaw/clawhub/pull/130
Author: @aleph8
Created: 2/4/2026
Status: Merged
Merged: 2/4/2026
Merged by: @steipete

Base: mainHead: feat/vt-integration-final


📝 Commits (5)

  • df35fe1 feat: implementation of dynamic VirusTotal integration and deterministic ZIPs
  • 17b1e8a fix: do not show security scan results if hash is missing
  • 6732ba0 ui: show 'Loading...' instead of 'Pending' while fetching VT results
  • d56efee security: restrict auto-approval to explicit benign verdicts only
  • c5ecc92 fix: prioritize AI verdict in results and refine stats fallback

📊 Changes

11 files changed (+713 additions, -11 deletions)

View changed files

📝 convex/_generated/api.d.ts (+2 -0)
📝 convex/downloads.ts (+39 -5)
📝 convex/http.ts (+1 -1)
📝 convex/lib/skillPublish.ts (+4 -0)
📝 convex/schema.ts (+2 -0)
📝 convex/skills.ts (+69 -2)
convex/vt.ts (+302 -0)
📝 packages/clawdhub/src/cli/commands/moderation.test.ts (+14 -2)
📝 packages/clawdhub/src/cli/commands/moderation.ts (+3 -1)
📝 src/components/SkillDetailPage.tsx (+159 -0)
📝 src/styles.css (+118 -0)

📄 Description

Hello, everyone!!! 🦞

This commit introduces automated skill review functionality using VirusTotal's Code Insight. 🥳

Context

Following recent security concerns and the discovery of potentially compromised or malicious skills in the ecosystem, this PR implements an automated security layer for ClawHub using Code Insight.

The idea is to filter skills before uploading them to the Hub so that they are validated before they are made public, with an automatic review.

Key changes

  1. All newly published skills and updates are now set to moderationStatus: 'hidden' with a reason of pending.scan..

  2. On convex/lib/skillPublish.ts has been integrated an asynchronous trigger to initiate the VirusTotal scan.

  3. The interaction process with VT is managed with the actions declared in convex/vt.ts. The results of the VT analysis are obtained by prioritizing the Code Insight verdict. If this verdict is not available, the antivirus engines that detect the file as malicious are displayed as a fallback.

  4. Dynamically generates a _meta.json file inside the scanned ZIP to provide VT with context. Previously, there were problems with generating the file hash, mainly due to the added timestamp. To solve this in a deterministic way, I added: constant date, alphabetical order of files in memory, and fixed compression level. On convex/downloads.ts and convex/vt.ts I unified the ZIP generation logic to be strictly deterministic. This ensures the hash scanned by VT is identical to the hash of the file downloaded by users.

  5. Added sha256hash field and by_sha256hash index to skillVersions for efficient dynamic lookups.

  6. Finally on the UI: added the SecurityScanResults component which handles "Loading..." states, displays the VirusTotal logo, and shows either the AI verdict or the engine detection ratio (e.g., 0/77 engines).

Screenshots

  • Clean Skill Example (AV Fallback)
image
  • Malicious Skill Example (Hub and the report on VT by Code Insight)
image image

Requirements

  • The environment variable VT_API_KEY must be configured in the Convex dashboard.
  • If the key is missing, as fallback, the system logs a warning, but the skill remains in the hidden quarantine state, requiring manual moderator intervention.

Verification steps

Once the VT API has been added to the environment:

  • Quarantine: Publish a test skill; confirm it is marked as "Hidden" in the dashboard.
  • Dynamic Fetch: Open the skill page and verify the security panel shows "Loading..." followed by the VT report status.
  • Hash Consistency: Run sha256sum on a downloaded skill ZIP; it must match the hash reported in the Security Scan UI.

Future Expansions

  • Currently, it is VT that automatically changes the moderation status once the analysis in the hub is complete, using the information from _meta. This could be automated by adding a task in convex/cron.ts that scans those that are hidden (once every X amount of time) and updates the status if the response from Code Insight with the fetch is benign.

  • The interface could be significantly improved. We could add something more visible, such as the Code Insight summary, or even add more verdicts.

  • Maybe a Molty VT? 🦞 🛡️

Feedback and suggestions

Any suggestions regarding the UI, the hashing algorithm, or the auto-approval logic are more than welcome :)

Greptile Overview

Greptile Summary

This PR adds a VirusTotal-based security scan pipeline for skills: new/updated skills are quarantined as hidden, an async Convex internal action builds a deterministic ZIP (including a generated _meta.json for VT context), computes/stores a SHA-256 hash for lookups, uploads to VT, and the UI displays scan status (AI verdict or engine ratio) on the skill detail page.

Key integration points are the new Convex actions in convex/vt.ts, schema/index additions for sha256hash, publish-time scan triggering, and a new SecurityScanResults UI block wired to api.vt.fetchResults.

Confidence Score: 2/5

  • This PR is not safe to merge until scan result interpretation and auto-approval behavior are corrected.
  • Core scan status logic in fetchResults can misclassify VT results, and scanWithVirusTotal can auto-approve non-benign Code Insight verdicts; additionally, the UI currently fans out dozens of VT requests per page view, likely triggering rate limits and breaking the feature in practice.
  • convex/vt.ts, src/components/SkillDetailPage.tsx

(2/5) Greptile learns from your feedback when you react with thumbs up/down!


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/openclaw/clawhub/pull/130 **Author:** [@aleph8](https://github.com/aleph8) **Created:** 2/4/2026 **Status:** ✅ Merged **Merged:** 2/4/2026 **Merged by:** [@steipete](https://github.com/steipete) **Base:** `main` ← **Head:** `feat/vt-integration-final` --- ### 📝 Commits (5) - [`df35fe1`](https://github.com/openclaw/clawhub/commit/df35fe174601d661b48ee9c33dad1a914763fd62) feat: implementation of dynamic VirusTotal integration and deterministic ZIPs - [`17b1e8a`](https://github.com/openclaw/clawhub/commit/17b1e8ac85dcd94a1b08e6f4d5bdc5d98e3338d9) fix: do not show security scan results if hash is missing - [`6732ba0`](https://github.com/openclaw/clawhub/commit/6732ba0880f6e664c98ac444692c2d3ea35b89a4) ui: show 'Loading...' instead of 'Pending' while fetching VT results - [`d56efee`](https://github.com/openclaw/clawhub/commit/d56efee3394a4251829128d44a6a059472a6088f) security: restrict auto-approval to explicit benign verdicts only - [`c5ecc92`](https://github.com/openclaw/clawhub/commit/c5ecc924481ce71c25e671273e63a8f340280b91) fix: prioritize AI verdict in results and refine stats fallback ### 📊 Changes **11 files changed** (+713 additions, -11 deletions) <details> <summary>View changed files</summary> 📝 `convex/_generated/api.d.ts` (+2 -0) 📝 `convex/downloads.ts` (+39 -5) 📝 `convex/http.ts` (+1 -1) 📝 `convex/lib/skillPublish.ts` (+4 -0) 📝 `convex/schema.ts` (+2 -0) 📝 `convex/skills.ts` (+69 -2) ➕ `convex/vt.ts` (+302 -0) 📝 `packages/clawdhub/src/cli/commands/moderation.test.ts` (+14 -2) 📝 `packages/clawdhub/src/cli/commands/moderation.ts` (+3 -1) 📝 `src/components/SkillDetailPage.tsx` (+159 -0) 📝 `src/styles.css` (+118 -0) </details> ### 📄 Description Hello, everyone!!! 🦞 This commit introduces automated skill review functionality using VirusTotal's Code Insight. 🥳 **Context** Following recent security concerns and the discovery of potentially compromised or malicious skills in the ecosystem, this PR implements an automated security layer for ClawHub using Code Insight. The idea is to filter skills before uploading them to the Hub so that they are validated before they are made public, with an automatic review. **Key changes** 1. All newly published skills and updates are now set to `moderationStatus: 'hidden'` with a reason of `pending.scan.`. 2. On `convex/lib/skillPublish.ts` has been integrated an asynchronous trigger to initiate the VirusTotal scan. 3. The interaction process with VT is managed with the actions declared in `convex/vt.ts`. The results of the VT analysis are obtained by prioritizing the Code Insight verdict. If this verdict is not available, the antivirus engines that detect the file as malicious are displayed as a fallback. 4. Dynamically generates a _meta.json file inside the scanned ZIP to provide VT with context. Previously, there were problems with generating the file hash, mainly due to the added timestamp. To solve this in a deterministic way, I added: constant date, alphabetical order of files in memory, and fixed compression level. On `convex/downloads.ts` and `convex/vt.ts` I unified the ZIP generation logic to be strictly deterministic. This ensures the hash scanned by VT is identical to the hash of the file downloaded by users. 5. Added sha256hash field and by_sha256hash index to skillVersions for efficient dynamic lookups. 6. Finally on the UI: added the SecurityScanResults component which handles "Loading..." states, displays the VirusTotal logo, and shows either the AI verdict or the engine detection ratio (e.g., 0/77 engines). **Screenshots** - Clean Skill Example (AV Fallback) <img width="741" height="333" alt="image" src="https://github.com/user-attachments/assets/bb592890-b16e-4a4d-a4ec-dd6343b89d3b" /> - Malicious Skill Example (Hub and the report on VT by Code Insight) <img width="1719" height="942" alt="image" src="https://github.com/user-attachments/assets/1f1c7c98-b863-4592-bc77-4e38e19ba071" /> <img width="1675" height="381" alt="image" src="https://github.com/user-attachments/assets/36a6fc54-1f3e-4f3b-a253-c2d16938c77d" /> **Requirements** - The environment variable VT_API_KEY must be configured in the Convex dashboard. - If the key is missing, as fallback, the system logs a warning, but the skill remains in the hidden quarantine state, requiring manual moderator intervention. **Verification steps** Once the VT API has been added to the environment: - Quarantine: Publish a test skill; confirm it is marked as "Hidden" in the dashboard. - Dynamic Fetch: Open the skill page and verify the security panel shows "Loading..." followed by the VT report status. - Hash Consistency: Run sha256sum on a downloaded skill ZIP; it must match the hash reported in the Security Scan UI. **Future Expansions** - Currently, it is VT that automatically changes the moderation status once the analysis in the hub is complete, using the information from _meta. This could be automated by adding a task in `convex/cron.ts` that scans those that are hidden (once every X amount of time) and updates the status if the response from Code Insight with the fetch is benign. - The interface could be significantly improved. We could add something more visible, such as the Code Insight summary, or even add more verdicts. - Maybe a Molty VT? 🦞 🛡️ **Feedback and suggestions** Any suggestions regarding the UI, the hashing algorithm, or the auto-approval logic are more than welcome :) <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR adds a VirusTotal-based security scan pipeline for skills: new/updated skills are quarantined as hidden, an async Convex internal action builds a deterministic ZIP (including a generated `_meta.json` for VT context), computes/stores a SHA-256 hash for lookups, uploads to VT, and the UI displays scan status (AI verdict or engine ratio) on the skill detail page. Key integration points are the new Convex actions in `convex/vt.ts`, schema/index additions for `sha256hash`, publish-time scan triggering, and a new `SecurityScanResults` UI block wired to `api.vt.fetchResults`. <h3>Confidence Score: 2/5</h3> - This PR is not safe to merge until scan result interpretation and auto-approval behavior are corrected. - Core scan status logic in `fetchResults` can misclassify VT results, and `scanWithVirusTotal` can auto-approve non-benign Code Insight verdicts; additionally, the UI currently fans out dozens of VT requests per page view, likely triggering rate limits and breaking the feature in practice. - convex/vt.ts, src/components/SkillDetailPage.tsx <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-02-15 17:16:34 -05:00
yindo closed this issue 2026-02-15 17:16:34 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: openclaw/clawhub#266