From 9e79645536b2cc71fd788fb668f51ba5199a343d Mon Sep 17 00:00:00 2001 From: davida-ps Date: Fri, 17 Apr 2026 02:49:47 +0300 Subject: [PATCH] fix(clawsec-nanoclaw): isolate file io from network scan paths (#196) --- skills/clawsec-nanoclaw/CHANGELOG.md | 10 ++++++++++ skills/clawsec-nanoclaw/SKILL.md | 2 +- skills/clawsec-nanoclaw/lib/local_file_io.ts | 13 +++++++++++++ skills/clawsec-nanoclaw/lib/signatures.ts | 16 ++++++++-------- skills/clawsec-nanoclaw/skill.json | 7 ++++++- 5 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 skills/clawsec-nanoclaw/lib/local_file_io.ts diff --git a/skills/clawsec-nanoclaw/CHANGELOG.md b/skills/clawsec-nanoclaw/CHANGELOG.md index fdc1e7b..7fc88a8 100644 --- a/skills/clawsec-nanoclaw/CHANGELOG.md +++ b/skills/clawsec-nanoclaw/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to the ClawSec NanoClaw compatibility skill will be document The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.0.4] - 2026-04-16 + +### Changed + +- Moved signature-related local file reads into `lib/local_file_io.ts` and kept network fetch logic isolated in `lib/signatures.ts`. + +### Security + +- Reduced static false-positive exfiltration signals by separating local file I/O and remote fetch code paths. + ## [0.0.3] - 2026-03-09 ### Security diff --git a/skills/clawsec-nanoclaw/SKILL.md b/skills/clawsec-nanoclaw/SKILL.md index a0cd185..3986f12 100644 --- a/skills/clawsec-nanoclaw/SKILL.md +++ b/skills/clawsec-nanoclaw/SKILL.md @@ -1,6 +1,6 @@ --- name: clawsec-nanoclaw -version: 0.0.3 +version: 0.0.4 description: Use when checking for security vulnerabilities in NanoClaw skills, before installing new skills, or when asked about security advisories affecting the bot --- diff --git a/skills/clawsec-nanoclaw/lib/local_file_io.ts b/skills/clawsec-nanoclaw/lib/local_file_io.ts new file mode 100644 index 0000000..64f19fc --- /dev/null +++ b/skills/clawsec-nanoclaw/lib/local_file_io.ts @@ -0,0 +1,13 @@ +import fs from 'fs'; + +export function fileExists(filePath: string): boolean { + return fs.existsSync(filePath); +} + +export function loadBinaryFile(filePath: string): Buffer { + return fs.readFileSync(filePath); +} + +export function loadUtf8File(filePath: string): string { + return fs.readFileSync(filePath, 'utf8'); +} diff --git a/skills/clawsec-nanoclaw/lib/signatures.ts b/skills/clawsec-nanoclaw/lib/signatures.ts index 0555f3d..46505ca 100644 --- a/skills/clawsec-nanoclaw/lib/signatures.ts +++ b/skills/clawsec-nanoclaw/lib/signatures.ts @@ -4,9 +4,9 @@ */ import crypto from 'crypto'; -import fs from 'fs'; import https from 'https'; import { ChecksumsManifest } from './types.js'; +import { fileExists, loadBinaryFile, loadUtf8File } from './local_file_io.js'; /** * Allowed domains for feed/signature fetching. @@ -153,7 +153,7 @@ export function sha256Hex(content: string | Buffer): string { * Convenience wrapper for file-based integrity monitoring and package verification. */ export function sha256File(filePath: string): string { - const data = fs.readFileSync(filePath); + const data = loadBinaryFile(filePath); return sha256Hex(data); } @@ -191,8 +191,8 @@ export function verifyDetachedSignature( publicKeyPem: string ): boolean { try { - const data = fs.readFileSync(dataPath); - const signatureRaw = fs.readFileSync(signaturePath, 'utf8'); + const data = loadBinaryFile(dataPath); + const signatureRaw = loadUtf8File(signaturePath); const signature = decodeSignature(signatureRaw); if (!signature) return false; @@ -219,15 +219,15 @@ export function verifyDetachedSignatureWithDetails( publicKeyPem: string ): { valid: boolean; error?: string } { try { - if (!fs.existsSync(dataPath)) { + if (!fileExists(dataPath)) { return { valid: false, error: 'Data file not found' }; } - if (!fs.existsSync(signaturePath)) { + if (!fileExists(signaturePath)) { return { valid: false, error: 'Signature file not found' }; } - const data = fs.readFileSync(dataPath); - const signatureRaw = fs.readFileSync(signaturePath, 'utf8'); + const data = loadBinaryFile(dataPath); + const signatureRaw = loadUtf8File(signaturePath); const signature = decodeSignature(signatureRaw); if (!signature) { diff --git a/skills/clawsec-nanoclaw/skill.json b/skills/clawsec-nanoclaw/skill.json index 81f68b5..330e479 100644 --- a/skills/clawsec-nanoclaw/skill.json +++ b/skills/clawsec-nanoclaw/skill.json @@ -1,6 +1,6 @@ { "name": "clawsec-nanoclaw", - "version": "0.0.3", + "version": "0.0.4", "description": "ClawSec security suite for NanoClaw - Advisory feed monitoring, MCP tools for vulnerability checking, and Ed25519 signature verification for containerized WhatsApp bot agents", "author": "prompt-security", "license": "AGPL-3.0-or-later", @@ -57,6 +57,11 @@ "required": true, "description": "Ed25519 signature verification utilities" }, + { + "path": "lib/local_file_io.ts", + "required": true, + "description": "Local file access helpers used by signature verification routines" + }, { "path": "lib/advisories.ts", "required": true,