Skip to main content
Version: Latest

Reports and Findings API

Scanner::run() returns an stdClass report after a completed scan. Scanner::getReport() returns the same current report shape. On a caught scan failure, run() returns false; inspect getLastError() on the scanner instance.

Top-level report contract

PropertyTypeMeaning
scannedintNumber of scanned files.
detectedintNumber of detected malware matches.
verifiedByChecksumintNumber of files accepted by checksum verification.
removed, ignored, edited, quarantine, whitelistarrayPaths or records affected by the matching action.
infectedFoundarrayInfected file paths found during the scan.
fileHashesarrayFile hash metadata collected during scanning.
findingsarrayCanonical finding records from file, integrity, archive, and supplemental analyses.
coveragearrayCompleteness, counts, and skip reasons.
diagnosticsarray, when presentNon-fatal analysis or definition update errors.
signature_indexesarrayBuilt-in and optional reputation-index metadata.
inventoryarray, when presentDetected platform component inventory.

New report fields can be added in a minor release. Consumers should read the fields they need, tolerate unknown fields, and use isset() for optional properties.

Handle success and failure

$report = $scanner->run();

if ($report === false) {
throw new RuntimeException($scanner->getLastError() ?: 'Scan failed.');
}

foreach ($report->findings as $finding) {
if ($finding['severity'] === 'danger') {
// Send the finding to your incident workflow.
}
}

Do not treat a nonzero detected count as an execution failure. Findings identify code or integrity conditions that need review. They do not establish intent or authorize deletion.

Finding record contract

Each canonical finding contains these fields:

FieldTypeMeaning
idstringStable SHA-256 identifier derived from the kind, provider, rule ID, and normalized subject.
kindstringFinding category, such as malware, integrity, or a supplemental analysis type.
subjectstringFile path or the scanned subject.
rule_idstringStable identifier for the detecting rule or indicator.
severitystringSeverity supplied by the detector, commonly warn or danger.
messagestringHuman-readable detection detail.
statusstringCurrent finding status. New findings start as open.
evidencearrayContext such as line, match, or content_hash when available.
providerstringDetector source, such as builtin.
first_seen_at, last_seen_atstringISO 8601 timestamps for the finding observation.

Keep rule_id, subject, and the observed content hash when deduplicating alerts. A line number or a snippet can change when a file changes.

Coverage is part of the result

The report includes coverage counts for discovered, eligible, scanned, skipped, verified, cached, and errors. coverage.reasons separates skipped files by path, extension, oversized, excluded, unreadable, and archive_limit.

Use this check before accepting a scan as complete:

$coverage = $report->coverage;

if (empty($coverage['complete']) || !empty($coverage['errors'])) {
throw new RuntimeException('Scan coverage is incomplete.');
}

Offset and limit batches, unreadable files, file-size limits, and archive limits can make the result incomplete. A complete zero-finding result carries more weight than a partial zero-finding result.

Diagnostics and external data

diagnostics reports non-fatal errors. For example, the scanner can continue with cached Maltrail definitions when an update fails. Persist diagnostics alongside findings so an operator can distinguish a clean result from reduced analysis.

signature_indexes exposes record counts and source hashes for the built-in malware and legacy-core indexes. When an active Maltrail store exists, it also includes domain-index metadata and its update time. Use those values for audit trails, not as a substitute for the finding evidence.

Serializing reports

Use json_encode() with error handling when you store the in-memory report:

$json = json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

if ($json === false) {
throw new RuntimeException('Could not serialize scan report: ' . json_last_error_msg());
}

Use setReportFormat('json') or setReportFormat('sarif') when the scanner should also write a file for external tooling. Choose a directory outside the scanned project for reports, checkpoints, backups, and quarantined files.