Drivers

The ClamAV Driver

Scanning uploads and payloads for malware with ClamAV.

Introduction

The ClamAV driver lets your API scan file uploads and other payloads for malware using ClamAV's clamd daemon.

It speaks the clamd INSTREAM protocol over TCP, so byte blobs are scanned in memory without ever being written to disk. Like other Kipchak drivers, it supports multiple named connections.

Installation

Install the driver via composer by running:

composer require kipchak/driver-clamav

Initialise the Driver

Add the following line to your drivers/drivers.php file:

\Kipchak\Driver\ClamAV\ClamAV::initialise($container);

Configuration

The configuration in kipchak.clamav.php can be used to configure multiple clamd connections. Each key is a connection name, resolvable with ClamAV::get('<name>'):

use function Kipchak\Core\env;

return [
    'default' => [
        'host'    => env('CLAMAV_HOST', '127.0.0.1'),
        'port'    => (int) env('CLAMAV_PORT', '3310'),
        'timeout' => (float) env('CLAMAV_TIMEOUT_SECONDS', '30'),
    ],
];

clamd listens on TCP port 3310 by default.

Usage

Scanning content

use Kipchak\Driver\ClamAV\ClamAV;

$result = ClamAV::get('default')->scan($uploadedFile->getStream()->getContents());

if (!$result->isClean()) {
    // Reject the upload. The matched signature name is available:
    $signature = $result->getSignature(); // e.g. "Eicar-Test-Signature"
}

scan() returns a ScanResult with two methods: isClean() and getSignature() (which is null for clean content).

Health checks

$healthy = ClamAV::get('default')->ping(); // true when clamd answers PONG

Failing open or closed

If clamd cannot be reached, scan() throws Kipchak\Driver\ClamAV\Exception\ConnectionException. The driver deliberately does not decide what happens next — catch the exception and choose whether an unreachable scanner rejects the upload (fail closed) or lets it through (fail open) for your use case:

use Kipchak\Driver\ClamAV\Exception\ConnectionException;

try {
    $result = ClamAV::get('default')->scan($bytes);
} catch (ConnectionException $e) {
    // Fail closed: treat an unreachable scanner as a rejection.
    return $this->response($response, ['error' => 'Upload could not be scanned'], 503);
}

Testing your own code

The client implements Kipchak\Driver\ClamAV\ScannerInterface, so you can inject a fake scanner in your tests without running a clamd daemon. For live testing, use the EICAR test signature.

Git Repository

The source code for this driver is available on 1x.ax at https://1x.ax/mamluk/kipchak/drivers/clamav.

Previous
ClouDNS