Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
2302632f11 | |||
a8c36a64b7 | |||
a810338cc4 | |||
c5049d5155 |
BIN
.serena/cache/typescript/document_symbols_cache_v23-06-25.pkl
vendored
Normal file
BIN
.serena/cache/typescript/document_symbols_cache_v23-06-25.pkl
vendored
Normal file
Binary file not shown.
35
.serena/memories/code_style_conventions.md
Normal file
35
.serena/memories/code_style_conventions.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Code Style and Conventions
|
||||
|
||||
## Naming Conventions
|
||||
- **Interfaces**: Prefix with `I` (e.g., `IUserData`)
|
||||
- **Types**: Prefix with `T` (e.g., `TResponseType`)
|
||||
- **Files**: Always lowercase (e.g., `classes.clamavservice.ts`)
|
||||
- **Classes**: PascalCase (e.g., `ClamAvService`)
|
||||
- **Methods/Functions**: camelCase (e.g., `scanBuffer`)
|
||||
- Avoid ENums when possible
|
||||
|
||||
## TypeScript Patterns
|
||||
- TypeScript-first approach with full type safety
|
||||
- ES modules (type: "module" in package.json)
|
||||
- Import dependencies in `ts/plugins.ts`
|
||||
- Reference with full path: `plugins.myModule.myClass()`
|
||||
|
||||
## File Organization
|
||||
- Source code in `ts/` directory
|
||||
- Tests in `test/` directory
|
||||
- Distribution in `dist_ts/` directory
|
||||
- Use `.js` extensions in imports for ES modules
|
||||
|
||||
## Testing Patterns
|
||||
- Use @git.zone/tstest framework
|
||||
- Import expect from @push.rocks/tapbundle
|
||||
- Test files end with `export default tap.start()`
|
||||
- Test naming: `*.both.ts`, `*.node.ts`, `*.browser.ts`
|
||||
- EICAR test string for antivirus verification
|
||||
|
||||
## General Principles
|
||||
- Make RAZOR SHARP changes - every modification must be goal-oriented
|
||||
- Improve elegance - changes should enhance clarity and maintainability
|
||||
- Preserve necessary complexity - don't oversimplify
|
||||
- Keep async patterns - maintain Promises where they add value
|
||||
- Remove redundancy carefully while preserving functionality
|
31
.serena/memories/project_overview.md
Normal file
31
.serena/memories/project_overview.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# SmartAntivirus Project Overview
|
||||
|
||||
## Purpose
|
||||
SmartAntivirus (@push.rocks/smartantivirus) is a Node.js/TypeScript library that provides enterprise-grade antivirus scanning capabilities by integrating with ClamAV. It allows developers to scan files, buffers, strings, and streams for viruses in their applications.
|
||||
|
||||
## Tech Stack
|
||||
- TypeScript (primary language)
|
||||
- Node.js (runtime)
|
||||
- ClamAV (antivirus engine)
|
||||
- Docker (for containerized ClamAV deployment)
|
||||
- Testing: @git.zone/tstest with @push.rocks/tapbundle
|
||||
- Build: @git.zone/tsbuild
|
||||
|
||||
## Architecture
|
||||
- **ClamAvService**: High-level interface for virus scanning operations
|
||||
- Scan strings, buffers, Node.js streams, and Web Streams
|
||||
- Auto-manages Docker container if needed
|
||||
- Connects to ClamAV daemon on port 3310
|
||||
|
||||
- **ClamAVManager**: Low-level Docker container management
|
||||
- Handles container lifecycle (start/stop)
|
||||
- Updates virus definitions
|
||||
- Provides log monitoring
|
||||
|
||||
## Key Features
|
||||
- In-memory scanning without disk I/O
|
||||
- Stream processing for large files
|
||||
- TypeScript-first with full type safety
|
||||
- Zero-config with sensible defaults
|
||||
- Auto-updating virus definitions
|
||||
- Docker-based or direct daemon connection
|
31
.serena/memories/suggested_commands.md
Normal file
31
.serena/memories/suggested_commands.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Suggested Commands for SmartAntivirus Development
|
||||
|
||||
## Build & Test Commands
|
||||
- `pnpm test` - Run test suite with tapbundle
|
||||
- `pnpm build` - Build TypeScript to JavaScript (uses tsbuild)
|
||||
- `pnpm run buildDocs` - Generate documentation (tsdoc)
|
||||
|
||||
## Development Tools
|
||||
- `tsbuild check test/**/* --skiplibcheck` - Type-check test files
|
||||
- `tsx test/test.ts` - Run individual test file directly
|
||||
|
||||
## Version Control
|
||||
- `git mv <old> <new>` - Move/rename files preserving history
|
||||
- `git status` - Check current changes
|
||||
- `git diff` - View uncommitted changes
|
||||
|
||||
## Package Management
|
||||
- `pnpm install` - Install dependencies
|
||||
- `pnpm install --save-dev <package>` - Add dev dependency
|
||||
- `pnpm add <package>` - Add production dependency
|
||||
|
||||
## File Operations
|
||||
- `ls` - List directory contents
|
||||
- `cat <file>` - View file contents
|
||||
- `find . -name "*.ts"` - Find TypeScript files
|
||||
- `rg <pattern>` - Search codebase with ripgrep
|
||||
|
||||
## Docker Management (if testing locally)
|
||||
- `docker ps` - List running containers
|
||||
- `docker logs clamav` - View ClamAV container logs
|
||||
- `docker stop clamav` - Stop ClamAV container
|
44
.serena/memories/task_completion_workflow.md
Normal file
44
.serena/memories/task_completion_workflow.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Task Completion Workflow
|
||||
|
||||
## Required Steps After Making Code Changes
|
||||
|
||||
1. **Build the Project**
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
Ensures TypeScript compiles without errors
|
||||
|
||||
2. **Run Tests**
|
||||
```bash
|
||||
pnpm test
|
||||
```
|
||||
Verifies functionality with test suite
|
||||
|
||||
3. **Type Check Test Files** (if tests were modified)
|
||||
```bash
|
||||
tsbuild check test/**/* --skiplibcheck
|
||||
```
|
||||
|
||||
## Quality Checks
|
||||
- Verify no TypeScript compilation errors
|
||||
- Ensure all tests pass
|
||||
- Check that new code follows existing patterns
|
||||
- Verify imports use `.js` extensions for ES modules
|
||||
- Confirm no hardcoded values that should be configurable
|
||||
|
||||
## Documentation Updates
|
||||
- Update readme.md if API changes
|
||||
- Add JSDoc comments for new public methods
|
||||
- Update changelog.md for version changes
|
||||
|
||||
## Before Committing
|
||||
- NEVER commit without explicit user approval
|
||||
- Use `git status` to review changes
|
||||
- Use `git diff` to verify modifications
|
||||
- Create focused commits with clear messages
|
||||
- Never commit secrets or API keys
|
||||
|
||||
## Important Notes
|
||||
- The project uses pnpm exclusively (not npm or yarn)
|
||||
- Always read documentation before using unfamiliar APIs
|
||||
- Check existing code patterns before implementing new features
|
68
.serena/project.yml
Normal file
68
.serena/project.yml
Normal file
@@ -0,0 +1,68 @@
|
||||
# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby)
|
||||
# * For C, use cpp
|
||||
# * For JavaScript, use typescript
|
||||
# Special requirements:
|
||||
# * csharp: Requires the presence of a .sln file in the project folder.
|
||||
language: typescript
|
||||
|
||||
# whether to use the project's gitignore file to ignore files
|
||||
# Added on 2025-04-07
|
||||
ignore_all_files_in_gitignore: true
|
||||
# list of additional paths to ignore
|
||||
# same syntax as gitignore, so you can use * and **
|
||||
# Was previously called `ignored_dirs`, please update your config if you are using that.
|
||||
# Added (renamed) on 2025-04-07
|
||||
ignored_paths: []
|
||||
|
||||
# whether the project is in read-only mode
|
||||
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
|
||||
# Added on 2025-04-18
|
||||
read_only: false
|
||||
|
||||
|
||||
# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
|
||||
# Below is the complete list of tools for convenience.
|
||||
# To make sure you have the latest list of tools, and to view their descriptions,
|
||||
# execute `uv run scripts/print_tool_overview.py`.
|
||||
#
|
||||
# * `activate_project`: Activates a project by name.
|
||||
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
|
||||
# * `create_text_file`: Creates/overwrites a file in the project directory.
|
||||
# * `delete_lines`: Deletes a range of lines within a file.
|
||||
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
|
||||
# * `execute_shell_command`: Executes a shell command.
|
||||
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
|
||||
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
|
||||
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
|
||||
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
|
||||
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
|
||||
# * `initial_instructions`: Gets the initial instructions for the current project.
|
||||
# Should only be used in settings where the system prompt cannot be set,
|
||||
# e.g. in clients you have no control over, like Claude Desktop.
|
||||
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
|
||||
# * `insert_at_line`: Inserts content at a given line in a file.
|
||||
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
|
||||
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
|
||||
# * `list_memories`: Lists memories in Serena's project-specific memory store.
|
||||
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
|
||||
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
|
||||
# * `read_file`: Reads a file within the project directory.
|
||||
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
|
||||
# * `remove_project`: Removes a project from the Serena configuration.
|
||||
# * `replace_lines`: Replaces a range of lines within a file with new content.
|
||||
# * `replace_symbol_body`: Replaces the full definition of a symbol.
|
||||
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
|
||||
# * `search_for_pattern`: Performs a search for a pattern in the project.
|
||||
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
|
||||
# * `switch_modes`: Activates modes by providing a list of their names
|
||||
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
|
||||
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
|
||||
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
|
||||
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
|
||||
excluded_tools: []
|
||||
|
||||
# initial prompt for the project. It will always be given to the LLM upon activating the project
|
||||
# (contrary to the memories, which are loaded on demand).
|
||||
initial_prompt: ""
|
||||
|
||||
project_name: "smartantivirus"
|
18
changelog.md
18
changelog.md
@@ -1,5 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-08-16 - 1.3.2 - fix(build)
|
||||
Bump dependencies, improve test/build scripts, expand documentation and add project metadata
|
||||
|
||||
- Updated devDependencies: bumped @git.zone/tsbuild, @git.zone/tsbundle, @git.zone/tstest, @push.rocks/tapbundle, @types/node and typescript to newer versions.
|
||||
- Updated runtime dependencies: bumped @push.rocks/smartfile, @push.rocks/smartpath and axios; tar version updated.
|
||||
- Adjusted npm scripts: test now runs with '(tstest test/ --web --verbose --logfile --timeout 120)'; build and docs scripts unchanged in behavior.
|
||||
- Added packageManager entry (pnpm) and a pnpm-workspace.yaml with onlyBuiltDependencies configured.
|
||||
- Expanded and rewrote README with detailed quick start, examples, API reference and troubleshooting guidance.
|
||||
- Added local assistant/IDE metadata and memories (.claude/settings.local.json and .serena/*) to aid development tooling and project onboarding.
|
||||
|
||||
## 2025-02-07 - 1.3.1 - fix(core)
|
||||
Updated descriptions and keywords in package.json and npmextra.json. Improved README content for usage clarity.
|
||||
|
||||
- Revised package.json description and keywords to better represent the project's features.
|
||||
- Enhanced npmextra.json with updated module attributes.
|
||||
- Improved README with clearer instructions and examples for using ClamAVManager and ClamAvService.
|
||||
- Fixed incorrect import path in test.clamav.manager.ts.
|
||||
|
||||
## 2025-02-05 - 1.3.0 - feat(ClamAvService)
|
||||
Add support for enhanced streaming methods in ClamAvService
|
||||
|
||||
|
@@ -5,21 +5,23 @@
|
||||
"githost": "code.foss.global",
|
||||
"gitscope": "push.rocks",
|
||||
"gitrepo": "smartantivirus",
|
||||
"description": "A Node.js package for integrating antivirus scanning capabilities using ClamAV, allowing in-memory file and data scanning.",
|
||||
"description": "A Node.js package providing integration with ClamAV for anti-virus scanning, facilitating both Docker containerized management and direct connection to a ClamAV daemon.",
|
||||
"npmPackagename": "@push.rocks/smartantivirus",
|
||||
"license": "MIT",
|
||||
"projectDomain": "push.rocks",
|
||||
"keywords": [
|
||||
"antivirus",
|
||||
"ClamAV",
|
||||
"Node.js",
|
||||
"ClamAV",
|
||||
"virus scanning",
|
||||
"security",
|
||||
"buffer scanning",
|
||||
"Docker",
|
||||
"in-memory scanning",
|
||||
"file scanning",
|
||||
"stream scanning",
|
||||
"data protection",
|
||||
"HTTP requests",
|
||||
"file handling",
|
||||
"network communication",
|
||||
"network security",
|
||||
"buffer scanning",
|
||||
"software testing"
|
||||
]
|
||||
}
|
||||
|
39
package.json
39
package.json
@@ -1,32 +1,32 @@
|
||||
{
|
||||
"name": "@push.rocks/smartantivirus",
|
||||
"version": "1.3.0",
|
||||
"version": "1.3.2",
|
||||
"private": false,
|
||||
"description": "A Node.js package for integrating antivirus scanning capabilities using ClamAV, allowing in-memory file and data scanning.",
|
||||
"description": "A Node.js package providing integration with ClamAV for anti-virus scanning, facilitating both Docker containerized management and direct connection to a ClamAV daemon.",
|
||||
"main": "dist_ts/index.js",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
"type": "module",
|
||||
"author": "Task Venture Capital GmbH",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "(tstest test/ --web)",
|
||||
"test": "(tstest test/ --web --verbose --logfile --timeout 120)",
|
||||
"build": "(tsbuild --web --allowimplicitany)",
|
||||
"buildDocs": "(tsdoc)"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^2.1.25",
|
||||
"@git.zone/tsbundle": "^2.0.5",
|
||||
"@git.zone/tsbuild": "^2.6.4",
|
||||
"@git.zone/tsbundle": "^2.5.1",
|
||||
"@git.zone/tsrun": "^1.2.46",
|
||||
"@git.zone/tstest": "^1.0.44",
|
||||
"@push.rocks/tapbundle": "^5.0.15",
|
||||
"@types/node": "^20.8.7",
|
||||
"typescript": "^5.7.3"
|
||||
"@git.zone/tstest": "^2.3.4",
|
||||
"@push.rocks/tapbundle": "^6.0.3",
|
||||
"@types/node": "^24.3.0",
|
||||
"typescript": "^5.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@push.rocks/smartfile": "^11.1.5",
|
||||
"@push.rocks/smartpath": "^5.0.18",
|
||||
"@push.rocks/smartfile": "^11.2.5",
|
||||
"@push.rocks/smartpath": "^6.0.0",
|
||||
"@push.rocks/smartstream": "^3.2.5",
|
||||
"axios": "^1.7.9",
|
||||
"axios": "^1.11.0",
|
||||
"tar": "^7.4.3"
|
||||
},
|
||||
"repository": {
|
||||
@@ -51,15 +51,18 @@
|
||||
],
|
||||
"keywords": [
|
||||
"antivirus",
|
||||
"ClamAV",
|
||||
"Node.js",
|
||||
"ClamAV",
|
||||
"virus scanning",
|
||||
"security",
|
||||
"buffer scanning",
|
||||
"Docker",
|
||||
"in-memory scanning",
|
||||
"file scanning",
|
||||
"stream scanning",
|
||||
"data protection",
|
||||
"HTTP requests",
|
||||
"file handling",
|
||||
"network communication",
|
||||
"network security",
|
||||
"buffer scanning",
|
||||
"software testing"
|
||||
]
|
||||
],
|
||||
"packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748"
|
||||
}
|
||||
|
4997
pnpm-lock.yaml
generated
4997
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
4
pnpm-workspace.yaml
Normal file
4
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
onlyBuiltDependencies:
|
||||
- esbuild
|
||||
- mongodb-memory-server
|
||||
- puppeteer
|
425
readme.md
425
readme.md
@@ -1,263 +1,306 @@
|
||||
# @push.rocks/smartantivirus
|
||||
# @push.rocks/smartantivirus 🛡️
|
||||
|
||||
A package for performing antivirus testing with ClamAV, featuring both direct daemon communication and Docker container management.
|
||||
**Enterprise-grade antivirus scanning for Node.js applications** - Seamlessly integrate ClamAV's powerful virus detection into your TypeScript/JavaScript projects with zero hassle.
|
||||
|
||||
## Features
|
||||
## Why SmartAntivirus? 🚀
|
||||
|
||||
- **Docker Integration**: Automatically manages ClamAV containers for easy setup and testing
|
||||
- **Real-time Logging**: Captures and processes ClamAV logs with type-safe event handling
|
||||
- **Database Management**: Supports automatic database updates and version tracking
|
||||
- **Flexible Scanning**: Scan strings, buffers, and files for malware
|
||||
- **Health Monitoring**: Built-in service readiness checks and connection verification
|
||||
In today's digital landscape, security is paramount. Whether you're building a file-sharing platform, processing user uploads, or handling sensitive data streams, you need reliable virus protection that just works. SmartAntivirus gives you:
|
||||
|
||||
- **🐳 Docker-based or Direct Connection** - Choose your deployment style
|
||||
- **⚡ In-memory Scanning** - Lightning-fast scanning without disk I/O
|
||||
- **🌊 Stream Processing** - Scan data on-the-fly as it flows through your app
|
||||
- **🎯 TypeScript First** - Full type safety and IntelliSense support
|
||||
- **📦 Zero Config** - Works out of the box with sensible defaults
|
||||
- **🔄 Auto-updating** - Virus definitions stay current automatically
|
||||
|
||||
## Install
|
||||
|
||||
Installing `@push.rocks/smartantivirus` is straightforward. You'll need Node.js and npm installed on your machine:
|
||||
|
||||
```bash
|
||||
npm install @push.rocks/smartantivirus
|
||||
```
|
||||
|
||||
### Prerequisites
|
||||
Or if you're using pnpm (recommended):
|
||||
|
||||
- Node.js and npm
|
||||
- Docker (for container-based usage)
|
||||
- ClamAV daemon (for direct daemon usage)
|
||||
|
||||
## Usage
|
||||
|
||||
The package provides two main ways to use ClamAV:
|
||||
|
||||
1. **Docker-based Usage** (Recommended): Uses `ClamAVManager` to automatically handle container lifecycle
|
||||
2. **Direct Daemon Usage**: Uses `ClamAvService` to communicate with an existing ClamAV daemon
|
||||
|
||||
Below is a comprehensive guide on how to use both approaches.
|
||||
|
||||
### Docker-based Usage with ClamAVManager
|
||||
|
||||
The `ClamAVManager` class provides a high-level interface for managing ClamAV in Docker containers:
|
||||
|
||||
```typescript
|
||||
import { ClamAVManager } from '@push.rocks/smartantivirus';
|
||||
|
||||
async function main() {
|
||||
// Create a new manager instance
|
||||
const manager = new ClamAVManager();
|
||||
|
||||
// Start the ClamAV container
|
||||
await manager.startContainer();
|
||||
|
||||
// Listen for log events
|
||||
manager.on('log', (event) => {
|
||||
console.log(`[ClamAV ${event.type}] ${event.message}`);
|
||||
});
|
||||
|
||||
// Get database information
|
||||
const dbInfo = await manager.getDatabaseInfo();
|
||||
console.log('Database Info:', dbInfo);
|
||||
|
||||
// Update virus definitions
|
||||
await manager.updateDatabase();
|
||||
|
||||
// When done, stop the container
|
||||
await manager.stopContainer();
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
```bash
|
||||
pnpm add @push.rocks/smartantivirus
|
||||
```
|
||||
|
||||
### Direct Daemon Usage with ClamAvService
|
||||
## Quick Start 🏃♂️
|
||||
|
||||
The primary interface provided by the package is the `ClamAvService` class. It allows you to scan data in memory or verify the connection to the ClamAV daemon.
|
||||
### The 5-Minute Setup
|
||||
|
||||
```typescript
|
||||
import { ClamAvService } from '@push.rocks/smartantivirus';
|
||||
|
||||
async function main() {
|
||||
const clamService = new ClamAvService('127.0.0.1', 3310); // Replace with your ClamAV host and port
|
||||
// That's it! The service automatically manages a Docker container
|
||||
const scanner = new ClamAvService();
|
||||
|
||||
// Verify connection to ClamAV
|
||||
const isConnected = await clamService.verifyConnection();
|
||||
console.log(`Connection to ClamAV: ${isConnected ? 'successful' : 'failed'}`);
|
||||
// Scan a suspicious string
|
||||
const result = await scanner.scanString('Is this text safe?');
|
||||
console.log(result.isInfected ? '⚠️ Threat detected!' : '✅ All clear!');
|
||||
|
||||
if (!isConnected) {
|
||||
console.error('Could not connect to ClamAV daemon. Please check your configuration.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Scan a text string
|
||||
const testString = 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*';
|
||||
const scanResult = await clamService.scanString(testString);
|
||||
console.log('Scan Result:', scanResult);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
// Scan a buffer
|
||||
const fileBuffer = await fs.readFile('./upload.pdf');
|
||||
const scanResult = await scanner.scanBuffer(fileBuffer);
|
||||
```
|
||||
|
||||
### Streaming Scanning
|
||||
## Core Concepts 💡
|
||||
|
||||
The `ClamAvService` supports scanning both NodeJS streams and Web API streams using three specialized methods:
|
||||
SmartAntivirus provides two main classes:
|
||||
|
||||
- `scanStream(stream: NodeJS.ReadableStream)`: Scans any NodeJS readable stream (files, network, etc.)
|
||||
- `scanWebStream(webstream: ReadableStream)`: Scans a Web API ReadableStream
|
||||
- `scanFileFromWebAsStream(url: string)`: Fetches and scans a file from a URL using NodeJS http/https
|
||||
### 🎯 ClamAvService
|
||||
The high-level interface for virus scanning. It handles all the complexity behind a simple, intuitive API.
|
||||
|
||||
#### Example Usage
|
||||
### 🐳 ClamAVManager
|
||||
Low-level Docker container management for advanced use cases. Most users won't need to interact with this directly.
|
||||
|
||||
## Real-World Examples 🌍
|
||||
|
||||
### Protecting File Uploads
|
||||
|
||||
```typescript
|
||||
import { ClamAvService } from '@push.rocks/smartantivirus';
|
||||
import express from 'express';
|
||||
import multer from 'multer';
|
||||
|
||||
const app = express();
|
||||
const scanner = new ClamAvService();
|
||||
const upload = multer({ storage: multer.memoryStorage() });
|
||||
|
||||
app.post('/upload', upload.single('file'), async (req, res) => {
|
||||
try {
|
||||
// Scan the uploaded file buffer
|
||||
const result = await scanner.scanBuffer(req.file.buffer);
|
||||
|
||||
if (result.isInfected) {
|
||||
return res.status(400).json({
|
||||
error: 'File rejected',
|
||||
threat: result.reason
|
||||
});
|
||||
}
|
||||
|
||||
// File is safe, proceed with storage
|
||||
await saveFile(req.file);
|
||||
res.json({ message: 'File uploaded successfully' });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Scan failed' });
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Streaming Large Files
|
||||
|
||||
Never load huge files into memory! Stream them instead:
|
||||
|
||||
```typescript
|
||||
import { ClamAvService } from '@push.rocks/smartantivirus';
|
||||
import { createReadStream } from 'fs';
|
||||
|
||||
async function main() {
|
||||
const clamService = new ClamAvService('127.0.0.1', 3310);
|
||||
const scanner = new ClamAvService();
|
||||
|
||||
// Example 1: Scanning a local file stream (NodeJS)
|
||||
const fileStream = createReadStream('path/to/local/file');
|
||||
const streamResult = await clamService.scanStream(fileStream);
|
||||
console.log('Stream Scan Result:', streamResult);
|
||||
|
||||
// Example 2: Scanning a web resource using NodeJS http/https
|
||||
const webResult = await clamService.scanFileFromWebAsStream('http://example.com/file');
|
||||
console.log('Web Stream Scan Result:', webResult);
|
||||
|
||||
// Example 3: Scanning a Web API ReadableStream
|
||||
const response = await fetch('http://example.com/file');
|
||||
if (response.body) {
|
||||
const webStreamResult = await clamService.scanWebStream(response.body);
|
||||
console.log('Web Stream API Scan Result:', webStreamResult);
|
||||
async function scanLargeFile(filePath: string) {
|
||||
const stream = createReadStream(filePath);
|
||||
const result = await scanner.scanStream(stream);
|
||||
|
||||
if (result.isInfected) {
|
||||
console.log(`🚨 Threat found: ${result.reason}`);
|
||||
// Quarantine or delete the file
|
||||
} else {
|
||||
console.log('✅ File is clean');
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
```
|
||||
|
||||
**Breaking Down the Example:**
|
||||
### Scanning Remote Content
|
||||
|
||||
1. **Initialization**: We start by creating an instance of the `ClamAvService` class. It takes two optional parameters: the host and port where your ClamAV daemon is running. By default, it assumes `127.0.0.1` and `3310`.
|
||||
Perfect for proxies, CDNs, or content moderation:
|
||||
|
||||
2. **Verify Connection**: The `verifyConnection` method is called to ensure that our application can communicate with the ClamAV daemon. It returns a promise that resolves to `true` if the connection is successful, and `false` otherwise.
|
||||
```typescript
|
||||
const scanner = new ClamAvService();
|
||||
|
||||
3. **Scan Strings**: We utilize the `scanString` method to scan a text string (in this example, the EICAR test virus string is used). This method converts the string to a buffer and sends it to the ClamAV daemon for scanning.
|
||||
// Scan a file from a URL
|
||||
const result = await scanner.scanFileFromWebAsStream('https://example.com/document.pdf');
|
||||
|
||||
### Handling Buffers
|
||||
// For browser environments using Web Streams API
|
||||
async function scanInBrowser(url: string) {
|
||||
const response = await fetch(url);
|
||||
const webStream = response.body as ReadableStream<Uint8Array>;
|
||||
|
||||
if (webStream) {
|
||||
const result = await scanner.scanWebStream(webStream);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Below is an example demonstrating scanning raw binary data in the form of buffers:
|
||||
### Advanced Container Management
|
||||
|
||||
For production environments requiring fine-grained control:
|
||||
|
||||
```typescript
|
||||
import { ClamAVManager } from '@push.rocks/smartantivirus';
|
||||
|
||||
class AntivirusService {
|
||||
private manager: ClamAVManager;
|
||||
|
||||
async initialize() {
|
||||
this.manager = new ClamAVManager();
|
||||
|
||||
// Start the container
|
||||
await this.manager.startContainer();
|
||||
|
||||
// Set up log monitoring
|
||||
this.manager.on('log', (event) => {
|
||||
if (event.type === 'error') {
|
||||
console.error(`ClamAV Error: ${event.message}`);
|
||||
// Send to your logging service
|
||||
}
|
||||
});
|
||||
|
||||
// Update virus definitions
|
||||
await this.manager.updateDatabase();
|
||||
|
||||
// Get database info
|
||||
const dbInfo = await this.manager.getDatabaseInfo();
|
||||
console.log(`Virus DB Version: ${dbInfo}`);
|
||||
}
|
||||
|
||||
async shutdown() {
|
||||
await this.manager.stopContainer();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing 🧪
|
||||
|
||||
We use the industry-standard EICAR test string for verification:
|
||||
|
||||
```typescript
|
||||
import { ClamAvService } from '@push.rocks/smartantivirus';
|
||||
|
||||
async function scanBufferExample() {
|
||||
const clamService = new ClamAvService();
|
||||
const scanner = new ClamAvService();
|
||||
|
||||
// This buffer should represent the binary data you want to scan.
|
||||
const buffer = Buffer.from('Sample buffer contents', 'utf8');
|
||||
// This is the EICAR test string - it's harmless but triggers antivirus
|
||||
const EICAR = 'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*';
|
||||
|
||||
try {
|
||||
const scanResult = await clamService.scanBuffer(buffer);
|
||||
console.log('Buffer Scan Result:', scanResult);
|
||||
} catch (error) {
|
||||
console.error('Error scanning buffer:', error);
|
||||
}
|
||||
}
|
||||
|
||||
scanBufferExample();
|
||||
const result = await scanner.scanString(EICAR);
|
||||
console.log(result.isInfected); // true
|
||||
console.log(result.reason); // 'Eicar-Test-Signature'
|
||||
```
|
||||
|
||||
**Explanation:**
|
||||
|
||||
- We create an instance of `ClamAvService`.
|
||||
- A buffer is created and passed to the `scanBuffer` method, which scans the in-memory data for potential viruses.
|
||||
|
||||
### Error Handling and Debugging
|
||||
|
||||
Both `ClamAVManager` and `ClamAvService` provide comprehensive error handling:
|
||||
|
||||
```typescript
|
||||
try {
|
||||
// Using ClamAVManager
|
||||
const manager = new ClamAVManager();
|
||||
await manager.startContainer();
|
||||
|
||||
// Listen for errors in logs
|
||||
manager.on('log', (event) => {
|
||||
if (event.type === 'error') {
|
||||
console.error(`ClamAV Error: ${event.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Using ClamAvService
|
||||
const service = new ClamAvService();
|
||||
const scanResult = await service.scanString('Some suspicious string...');
|
||||
console.log(`Infection Status: ${scanResult.isInfected ? 'Infected' : 'Clean'}`);
|
||||
if (scanResult.isInfected) {
|
||||
console.log(`Reason: ${scanResult.reason}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('An error occurred during the scanning process:', error);
|
||||
}
|
||||
```
|
||||
|
||||
### Testing your setup
|
||||
|
||||
A preconfigured test script is provided, which demonstrates how to use the package with the Tap bundle testing framework. You can find the test script in `test/test.ts`. This is configured to run with the default `@push.rocks/tapbundle` setup:
|
||||
Run the test suite:
|
||||
|
||||
```bash
|
||||
npm run test
|
||||
npm test
|
||||
```
|
||||
|
||||
The tests include creating and utilizing a `ClamAvService` instance and attempts to scan the well-known EICAR test string. They ensure that the basic functionality of the package is working as intended.
|
||||
## API Reference 📚
|
||||
|
||||
### Advanced Usage and Integration
|
||||
|
||||
#### Container Configuration
|
||||
|
||||
The `ClamAVManager` supports customizing the Docker container:
|
||||
### ClamAvService
|
||||
|
||||
#### Constructor
|
||||
```typescript
|
||||
const manager = new ClamAVManager();
|
||||
|
||||
// Container properties are configurable
|
||||
console.log(manager.containerName); // 'clamav-daemon'
|
||||
console.log(manager.port); // 3310
|
||||
new ClamAvService(host?: string, port?: number)
|
||||
```
|
||||
- `host` - ClamAV daemon host (default: '127.0.0.1')
|
||||
- `port` - ClamAV daemon port (default: 3310)
|
||||
|
||||
#### Log Management
|
||||
#### Methods
|
||||
|
||||
Access and process ClamAV logs:
|
||||
##### `scanString(text: string): Promise<ScanResult>`
|
||||
Scan a text string for threats.
|
||||
|
||||
##### `scanBuffer(buffer: Buffer): Promise<ScanResult>`
|
||||
Scan binary data in a Buffer.
|
||||
|
||||
##### `scanStream(stream: NodeJS.ReadableStream): Promise<ScanResult>`
|
||||
Scan a Node.js readable stream.
|
||||
|
||||
##### `scanWebStream(stream: ReadableStream<Uint8Array>): Promise<ScanResult>`
|
||||
Scan a Web Streams API stream (browser-compatible).
|
||||
|
||||
##### `scanFileFromWebAsStream(url: string): Promise<ScanResult>`
|
||||
Download and scan a file from a URL.
|
||||
|
||||
##### `verifyConnection(): Promise<boolean>`
|
||||
Test the connection to ClamAV daemon.
|
||||
|
||||
#### ScanResult Type
|
||||
```typescript
|
||||
const manager = new ClamAVManager();
|
||||
|
||||
// Get all logs
|
||||
const logs = manager.getLogs();
|
||||
|
||||
// Filter logs by type
|
||||
const errorLogs = logs.filter(log => log.type === 'error');
|
||||
const updateLogs = logs.filter(log => log.type === 'update');
|
||||
interface ScanResult {
|
||||
isInfected: boolean;
|
||||
reason?: string; // Threat name if infected
|
||||
}
|
||||
```
|
||||
|
||||
#### Health Checks
|
||||
### ClamAVManager
|
||||
|
||||
Monitor ClamAV service health:
|
||||
Advanced container management for production deployments:
|
||||
|
||||
```typescript
|
||||
const manager = new ClamAVManager();
|
||||
- `startContainer()` - Launch ClamAV in Docker
|
||||
- `stopContainer()` - Gracefully shutdown
|
||||
- `updateDatabase()` - Update virus definitions
|
||||
- `getDatabaseInfo()` - Get current DB version
|
||||
- `getLogs()` - Retrieve container logs
|
||||
- Event: `'log'` - Real-time log streaming
|
||||
|
||||
// Service automatically checks readiness during initialization
|
||||
await manager.startContainer(); // Includes readiness checks
|
||||
## Production Considerations 🏭
|
||||
|
||||
// Get database status
|
||||
const dbInfo = await manager.getDatabaseInfo();
|
||||
console.log('Database Version:', dbInfo);
|
||||
### Performance Tips
|
||||
|
||||
1. **Reuse connections** - Create one `ClamAvService` instance and reuse it
|
||||
2. **Stream large files** - Don't load them into memory
|
||||
3. **Implement timeouts** - Protect against hanging scans
|
||||
4. **Monitor logs** - Watch for database update failures
|
||||
|
||||
### Security Best Practices
|
||||
|
||||
- Run ClamAV container with limited resources
|
||||
- Implement rate limiting on scan endpoints
|
||||
- Log all detected threats for audit trails
|
||||
- Regularly update virus definitions
|
||||
- Use separate containers for different environments
|
||||
|
||||
### Deployment Options
|
||||
|
||||
#### Docker Compose
|
||||
```yaml
|
||||
services:
|
||||
clamav:
|
||||
image: clamav/clamav:latest
|
||||
ports:
|
||||
- "3310:3310"
|
||||
volumes:
|
||||
- clamav-db:/var/lib/clamav
|
||||
```
|
||||
|
||||
You can build upon these functionalities to implement advanced use cases such as:
|
||||
- Automated virus scanning in CI/CD pipelines
|
||||
- Real-time file monitoring in web applications
|
||||
- Cloud-based malware detection services
|
||||
- Integration with security information and event management (SIEM) systems
|
||||
#### Kubernetes
|
||||
The service automatically manages containers, but you can also deploy ClamAV separately and connect directly to the daemon.
|
||||
|
||||
With the help of Node.js worker threads or external task queues like RabbitMQ, you can distribute scanning tasks efficiently within high-traffic environments.
|
||||
## Troubleshooting 🔧
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Container won't start**
|
||||
- Ensure Docker is running
|
||||
- Check port 3310 isn't already in use
|
||||
- Verify sufficient disk space for virus definitions
|
||||
|
||||
**Scans timing out**
|
||||
- Large files may take time - implement appropriate timeouts
|
||||
- Check container resources (CPU/Memory)
|
||||
- Ensure virus database is not updating
|
||||
|
||||
**False positives**
|
||||
- Some packers/obfuscators trigger detection
|
||||
- Whitelist known-safe patterns if needed
|
||||
- Keep virus definitions updated
|
||||
|
||||
## Contributing & Support 🤝
|
||||
|
||||
- 🐛 [Report Issues](https://code.foss.global/push.rocks/smartantivirus/issues)
|
||||
- 📖 [Documentation](https://code.foss.global/push.rocks/smartantivirus)
|
||||
- 💬 [Discussions](https://code.foss.global/push.rocks/smartantivirus/issues)
|
||||
|
||||
## License and Legal Information
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { expect, tap } from '../ts/plugins.js';
|
||||
import { expect, tap } from '@push.rocks/tapbundle';
|
||||
import type { ClamAVLogEvent } from '../ts/classes.clamav.manager.js';
|
||||
import { setupClamAV, cleanupClamAV, getManager } from './helpers/clamav.helper.js';
|
||||
|
||||
|
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartantivirus',
|
||||
version: '1.3.0',
|
||||
description: 'A Node.js package for integrating antivirus scanning capabilities using ClamAV, allowing in-memory file and data scanning.'
|
||||
version: '1.3.2',
|
||||
description: 'A Node.js package providing integration with ClamAV for anti-virus scanning, facilitating both Docker containerized management and direct connection to a ClamAV daemon.'
|
||||
}
|
||||
|
Reference in New Issue
Block a user