KicomAV v0.41

February 3, 2026 ยท View on GitHub

KicomAV v0.41

License Platform Platform Platform
Language PyPI Downloads
Sponsor

KicomAV is an open source antivirus engine designed for detecting malware and disinfecting it. This antivirus engine is created and maintained by Kei Choi.

Sponsorship

KicomAV is maintained as a production-grade open-source antivirus engine. Sponsorship keeps the engine stable, continuously improved, and usable for real security work.

kicomav-x is a high-performance experimental antivirus engine implemented in Rust. It is currently private due to its experimental nature. Once KicomAV reaches a sustainable sponsorship level, kicomav-x will be opened as part of the project.

Features

  • Multi-format scanning: Files, archives (ZIP, RAR, 7z, CAB, ALZ, EGG, APK, OneNote), and nested containers
  • YARA integration: Custom YARA rules support for advanced threat detection
  • Intelligent caching: Dual-cache system with scan mode awareness for consistent, fast rescans
  • Exclusion rules: Flexible file/directory exclusion with glob patterns
  • Parallel scanning: Multi-threaded scanning for improved performance
  • Daemon mode: REST API and clamd-compatible socket protocol
  • Cross-platform: Windows, Linux, macOS support
  • Library API: Use as a Python library in your projects
  • PyInstaller support: Scan PyInstaller executables (Windows PE and Linux ELF)

Table of Contents

Requirements

Daemon mode dependencies (k2d, k2c):

Optional dependencies:

  • pylzma - LZMA compression (for NSIS)

Installation

pip install kicomav

From source

git clone https://github.com/hanul93/kicomav.git
cd kicomav
pip install -e .

With daemon support

pip install kicomav[daemon]

Configuration

KicomAV uses environment variables for configuration. Create a .env file in your home directory:

Windows:

mkdir %USERPROFILE%\.kicomav
copy .env.example %USERPROFILE%\.kicomav\.env

Linux/macOS:

mkdir -p ~/.kicomav
cp .env.example ~/.kicomav/.env

Then edit ~/.kicomav/.env to configure:

VariableDescriptionExample
UNRAR_TOOLPath to UnRAR executable/usr/bin/unrar or C:\Program Files\WinRAR\UnRAR.exe
RAR_TOOLPath to RAR executable/usr/bin/rar or C:\Program Files\WinRAR\Rar.exe
SYSTEM_RULES_BASESystem rules path/var/lib/kicomav/rules or C:\kicomav\rules
USER_RULES_BASEUser rules path/home/user/kicomav_rules or C:\kicomav\user_rules

Note: You can also place a .env file in the current working directory for project-specific settings (takes priority over global settings).

Components

KicomAV provides three command-line tools:

ToolDescription
k2Main scanner - scan files and directories for malware
k2dDaemon server - REST API and socket protocol service
k2cClient - communicate with k2d daemon

Quick Overview

  • Standalone scanning: Use k2 directly for local file scanning
  • Client-server mode: Run k2d as a service, use k2c to send scan requests

Command-Line Usage (k2)

$ k2 path[s] [options]

Basic Options

OptionDescription
-f, --filesScan files (default)
-r, --arcScan archives
-R, --norDo not recurse into folders
-I, --listDisplay all files
-V, --vlistDisplay virus list
-?, --helpShow help

Scan Actions

OptionDescription
-p, --promptPrompt for action
-d, --disDisinfect files
-l, --delDelete infected files
--moveMove infected files to quarantine
--copyCopy infected files to quarantine

Performance Options

OptionDescription
--parallelEnable parallel file scanning
--workers=NNumber of worker threads (default: CPU count)
--cacheEnable scan cache (default)
--no-cacheDisable scan cache

Other Options

OptionDescription
-G, --log=FILECreate log file
-e, --appAppend to log file
-F, --infp=PATHSet quarantine folder
--password=PWDPassword for encrypted archives
--no-colorDisable colored output
--sigtoolExtract files from archives to output folder
--updateUpdate malware signatures

Examples

Update signatures:

$ k2 --update

Scan current directory:

$ k2 . -I

Scan with archive support:

$ k2 /path/to/scan -r -I

Parallel scanning with 8 workers:

$ k2 /path/to/scan --parallel --workers=8

Scan and disinfect:

$ k2 /path/to/scan -d

Advanced Features

Exclusion Rules

KicomAV supports flexible file exclusion to skip unwanted files during scans.

Command-Line Options

OptionDescriptionExample
--exclude=PATTERNExclude files matching glob pattern--exclude=*.log
--exclude-ext=EXTExclude by extension (comma-separated)--exclude-ext=log,tmp
--max-size=SIZESkip files larger than size--max-size=100MB
--ignore-file=FILELoad rules from file--ignore-file=.kicomav-ignore

Size units: B, KB, MB, GB

Examples

# Skip log files and files over 50MB
k2 /path/to/scan --exclude-ext=log --max-size=50MB

# Skip multiple patterns
k2 /path/to/scan --exclude=**/node_modules/** --exclude=**/cache/**

# Use an ignore file
k2 /path/to/scan --ignore-file=.kicomav-ignore

Ignore File Format (.kicomav-ignore)

Create a .kicomav-ignore file (similar to .gitignore):

# Comment lines start with #
*.log                    # Exclude all .log files
*.tmp                    # Exclude all .tmp files
node_modules/            # Exclude node_modules directory
build/                   # Exclude build directory
**/cache/**              # Exclude cache directories anywhere
>100MB                   # Skip files larger than 100MB

Ignore file search order:

  1. Current directory
  2. Parent directories (up to root)
  3. ~/.kicomav/.kicomav-ignore

Pattern Matching

PatternMatchesDoes Not Match
*.logapp.log, error.logapp.txt, log.txt
**/cache/**/project/cache/file.txt/project/cached/file.txt
node_modules//project/node_modules/pkg.json/project/my_modules/pkg.json
file?.txtfile1.txt, fileA.txtfile10.txt, file.txt

Library Usage

from kicomav.kavcore.k2exclude import ExclusionRule, create_exclusion_rule

# Create rule with factory function
rule = create_exclusion_rule(
    patterns=["**/node_modules/**", "**/cache/**"],
    extensions=["log", "tmp", "bak"],
    max_size="100MB"
)

# Check if a file should be excluded
if rule.should_exclude("/path/to/file.log"):
    print("File excluded")

Scan Cache

KicomAV supports intelligent caching to skip unchanged files during rescans, significantly improving scan performance.

How It Works

  • SQLite database stored at ~/.kicomav/cache.db
  • Dual cache system: Separate caches for regular files and archives
  • Files are skipped if unchanged since last scan
  • Cache invalidates when signature version changes
  • Configurable expiration period (default: 7 days)

Cache Architecture

KicomAV uses a sophisticated dual-cache system:

Cache TypePurposeKey
scan_cacheRegular filesfile_path
archive_cacheArchives (ZIP, RAR, 7z, etc.)(archive_path, scan_mode)

Scan Mode Awareness: The archive cache tracks whether -r (deep archive scan) option was used:

  • -I and -r -I scans maintain separate cache entries
  • Switching between scan modes produces consistent results
  • Each mode's statistics (Files, Packed, Infected) are preserved independently

Archive Cache Features

  • Contents hash: Archives identified by hash of internal file list
  • Infection tracking: Cached results include infected file paths with malware names
  • Statistics preservation: File count, packed count, and scan paths are cached
  • Smart revalidation: Re-compressed archives with same files remain cache-valid

Command-Line Options

OptionDescriptionDefault
--cacheEnable scan cacheEnabled
--no-cacheDisable scan cache-
--cache-clearClear all cache entries-
--cache-statsShow cache statistics-
--cache-expire=DAYSSet expiration (0=never)7

Examples

# Scan with cache (default behavior)
k2 /path/to/scan -r

# Disable cache for fresh scan
k2 /path/to/scan -r --no-cache

# View cache statistics
k2 --cache-stats

# Clear cache
k2 --cache-clear

# Set 30-day cache expiration
k2 /path/to/scan --cache-expire=30

Cache Statistics Output

Scan Cache Statistics
----------------------------------------
Cache path: ~/.kicomav/cache.db
Cache size: 1.2MB
Total entries: 5532 (files: 5432, archives: 100)
Clean files: 5410
Infected files: 22
Clean archives: 95
Infected archives: 5
Expired entries: 128
Expire days: 7

Cache Invalidation

The cache automatically invalidates when:

  1. File modified: File size or modification time changed
  2. Signature updated: Signature version differs from cached version
  3. Cache expired: Entry older than expiration period
  4. File deleted: Entry removed during maintenance
  5. Scan mode changed: Archive scanned with different -r option (archive cache only)
  6. Contents changed: Archive internal file list differs (archive cache only)

Performance Impact

Example scan times with caching enabled:

ScanOptionTimeNotes
First-r -I~40sFull scan, cache populated
Second-r -I~2sCache hit
Third-I~18sDifferent mode, separate cache
Fourth-I~0sCache hit
Fifth-r -I~2sReturns to cached -r results

This ensures:

  • Rescanning unchanged files/archives is nearly instant
  • Different scan modes maintain independent, consistent results
  • Infected entries from previous scans are reported from cache

Library Usage

from kicomav.kavcore.k2cache import (
    ScanCache, compute_file_hash, compute_contents_hash, create_cache
)

# Create cache with custom expiration
cache = create_cache(expire_days=14)

# Check if file needs scanning
if cache.needs_scan("/path/to/file", signature_version="1.0"):
    file_hash = compute_file_hash("/path/to/file")
    cache.update("/path/to/file", file_hash, "clean", signature_version="1.0")
else:
    result = cache.get_cached_result("/path/to/file", "1.0")
    if result:
        scan_result, malware_name = result
        print(f"Cached result: {scan_result}")

# Archive cache usage
# Create contents hash from archive entries (filename, size, crc)
entries = [("file1.txt", 100, 12345), ("file2.txt", 200, 67890)]
contents_hash = compute_contents_hash(entries)

# opt_arc parameter controls cache separation:
# - opt_arc=False: -I option (partial archive scan)
# - opt_arc=True: -r -I option (full archive scan)
opt_arc = True  # Using -r option

# Check if archive needs scanning
if cache.needs_archive_scan("/path/to/archive.zip", contents_hash, "1.0", opt_arc):
    # Perform archive scan...
    # After scanning, update cache with results
    infected = [{"path": "malware.exe", "malware": "Trojan.Test"}]
    cache.update_archive(
        "/path/to/archive.zip",
        archive_hash="abc123",
        contents_hash=contents_hash,
        scan_result="infected",
        infected_entries=infected,
        signature_version="1.0",
        opt_arc=opt_arc  # Store scan mode
    )
else:
    # Use cached archive result
    result = cache.get_archive_cached_result(
        "/path/to/archive.zip", contents_hash, "1.0", opt_arc
    )
    if result:
        scan_result, infected_entries, total_files, total_packed, scanned_paths = result
        print(f"Archive result: {scan_result}")
        print(f"Files: {total_files}, Packed: {total_packed}")
        for entry in infected_entries:
            print(f"  Infected: {entry['path']} - {entry['malware']}")

# Get statistics
stats = cache.get_stats()
print(f"Total entries: {stats['total_entries']}")
print(f"File entries: {stats['file_entries']}")
print(f"Archive entries: {stats['archive_entries']}")

# Maintenance
cache.prune_expired()   # Remove expired entries
cache.prune_missing()   # Remove entries for deleted files
cache.vacuum()          # Compact database
cache.close()

Parallel Scanning

Enable multi-threaded scanning for improved performance on multi-core systems.

# Auto-detect CPU count
k2 /path/to/scan --parallel

# Specify worker count
k2 /path/to/scan --parallel --workers=8

Library Usage

KicomAV can be used as a Python library in your projects.

Basic Scanning

import kicomav

# Scan a single file
with kicomav.Scanner() as scanner:
    result = scanner.scan_file("/path/to/suspicious_file.exe")
    if result.infected:
        print(f"Malware detected: {result.malware_name}")
    else:
        print("File is clean")

Directory Scanning

import kicomav

# Scan an entire directory
with kicomav.Scanner() as scanner:
    results = scanner.scan_directory("/path/to/folder", recursive=True)

    infected_files = [r for r in results if r.infected]
    print(f"Scanned {len(results)} files, found {len(infected_files)} infected")

    for result in infected_files:
        print(f"  {result.path}: {result.malware_name}")

Updating Signatures

import kicomav

result = kicomav.update()

if result.package_update_available:
    print(f"New version available: {result.latest_version}")

if result.updated_files:
    print(f"Updated {len(result.updated_files)} signature files")

Configuration Access

import kicomav

config = kicomav.get_config()
print(f"System rules path: {config.system_rules_base}")
print(f"User rules path: {config.user_rules_base}")

Suppress Warnings

from kicomav.kavcore.config import suppress_warnings
suppress_warnings(True)

import kicomav  # No configuration warnings

Archive Exploration

KicomAV provides high-level APIs for exploring and extracting archives.

import kicomav

# List archive contents
with kicomav.Scanner() as scanner:
    info, entries = scanner.list_archive("/path/to/archive.zip")
    print(f"Format: {info.format_type}")
    for entry in entries:
        print(f"{'  '*entry.depth}{entry.path}")

# Extract archive to a folder
with kicomav.Scanner() as scanner:
    result = scanner.extract_archive(
        "/path/to/archive.zip",
        "/output/folder"
    )
    print(f"Extracted {result.extracted_count} files")
    print(f"Log file: {result.log_file}")

# Read a single file from archive into memory
with kicomav.Scanner() as scanner:
    data = scanner.read_archive("/path/to/archive.zip", "config.json")
    if data:
        import json
        config = json.loads(data.decode('utf-8'))

Supported Formats: ZIP, RAR, 7z, CAB, ALZ, EGG, TAR, GZ, BZ2, APK, OneNote, PyInstaller (PE/ELF)

Exception Handling:

import kicomav

try:
    with kicomav.Scanner() as scanner:
        result = scanner.extract_archive("/path/to/archive.zip", "/output")
except kicomav.ArchiveNotFoundError:
    print("Archive file not found")
except kicomav.ArchiveFormatError:
    print("Unsupported or corrupted archive format")
except kicomav.ArchivePasswordError:
    print("Archive is password protected")
except kicomav.ArchiveSecurityError:
    print("Security issue detected (e.g., path traversal)")
except kicomav.ArchiveExtractionError as e:
    print(f"Extraction failed: {e}")

Advanced: Direct Engine Access

import kicomav

engine = kicomav.Engine(verbose=True)
engine.set_plugins("/path/to/plugins")

instance = engine.create_instance()
instance.init()

# Get engine information
info = instance.getinfo()
for plugin_info in info:
    print(f"Plugin: {plugin_info.get('title')}")

# Scan with callback
def on_detect(result, filename, malware_name, malware_id):
    print(f"Detected: {malware_name} in {filename}")

instance.scan("/path/to/file.exe", on_detect)
instance.uninit()

Daemon Mode (k2d & k2c)

KicomAV can run as a daemon server, providing both REST API and clamd-compatible socket protocol.

Server (k2d)

# Start both REST API and Socket server
k2d

# Start REST API only (port 8311)
k2d --http-only

# Start Socket server only (port 3311)
k2d --socket-only

# Generate API key for authentication
k2d --generate-key

Server Configuration

VariableDefaultDescription
K2D_HTTP_HOST127.0.0.1HTTP bind address
K2D_HTTP_PORT8311HTTP port
K2D_SOCKET_PORT3311Socket port
K2D_MAX_UPLOAD_SIZE52428800Max upload size (50MB)
K2D_MAX_WORKERSCPU countMax concurrent workers
K2D_API_KEY-API key for authentication
K2D_REQUIRE_AUTHfalseRequire authentication

Client (k2c)

k2c is a command-line client for communicating with the k2d daemon.

# Server status
k2c --ping                     # Check server connection
k2c --version                  # Get version info
k2c --stats                    # Get statistics

# Scan files
k2c /path/to/file              # Scan a file
k2c /path/to/folder            # Scan a directory
k2c --stream < suspicious.exe  # Scan from stdin

# Connection options
k2c --host 192.168.1.100       # Connect to remote server
k2c --socket                   # Use socket protocol
k2c --api-key YOUR_KEY         # Authentication

# Cache management
k2c --cache-stats              # View cache statistics
k2c --cache-clear              # Clear cache

# Output options
k2c --json                     # JSON output
k2c -q                         # Only show infected files

Example

$ k2c eicar.txt
============================================================
KicomAV Client (k2c) v0.41
============================================================

eicar.txt  infected : EICAR-Test-File (not a virus)

----------------------------------------
Files scanned: 1
Infected: 1
Errors: 0

REST API

MethodEndpointDescription
GET/pingHealth check
GET/versionVersion and signature info
GET/statsScan statistics
POST/scan/fileScan uploaded file
POST/scan/pathScan local path
POST/scan/streamScan base64 encoded data
POST/reloadReload signatures

Examples:

# Health check
curl http://127.0.0.1:8311/ping

# Scan a file
curl -X POST -F "file=@suspicious.exe" http://127.0.0.1:8311/scan/file

# Scan a directory
curl -X POST -H "Content-Type: application/json" \
  -d '{"path": "/path/to/scan", "recursive": true}' \
  http://127.0.0.1:8311/scan/path

Socket Protocol (clamd-compatible)

CommandDescription
PINGHealth check (returns PONG)
VERSIONGet version info
STATSGet statistics
SCAN <path>Scan a file
CONTSCAN <path>Scan directory recursively
INSTREAMScan streamed data
RELOADReload signatures

Example (Python):

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("127.0.0.1", 3311))

# PING test
sock.send(b"PING\n")
print(sock.recv(1024))  # b'PONG\n'

# Scan a file
sock.send(b"SCAN /path/to/file.exe\n")
print(sock.recv(1024))  # b'/path/to/file.exe: OK\n'

sock.close()

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Kei Choi