11458 Commits

Author SHA1 Message Date
Val S.
59eaa63c94 Win32: fix opendir entry bounds handling (#1706)
opendir() copied up to PATH_MAX wide characters into DIR::entry
and then wrote the terminator one element past the end of the
buffer, leaving a fixed out-of-bounds write on success.
We do not believe this to be a security issue.

Copy at most entry_count - 1 characters, terminate the last
valid element, keep the append length check aligned with that
bound, and free DIR when uncpath() fails.

CLAM-2487
2026-05-19 18:05:35 -04:00
Val S.
c28ccc3811 Merge pull request #1697 from val-ms/CLAM-2946-egg-parser-issue
Fix short writes in scanner temp output paths
2026-05-08 16:24:54 -04:00
Valerie Snyder
f1847f27b9 Fix short writes in scanner temp output paths
Fix an EGG comment temp-file bug where the write length used the
number of comments instead of the length of the current comment.

Also switch raw write paths in scanners.c to cli_writen() so short
writes are handled correctly for RAR comments, kept EGG comments,
extracted EGG temp files, normalized script output, and UTF-16 HTML
temp output.

CLAM-2946
2026-05-08 16:24:24 -04:00
sharkautarch
3674873f45 ClamOnAcc: Fix hash bucket list corruption on collision (#1712)
When onas_ht_insert() adds an element whose hash maps to an existing
bucket, the bucket is already part of the activated-bucket list. The old
code appended that same bucket to the list again, resetting bckt->next to
NULL and making any following buckets unreachable from ht->head.

OnAccessExcludePath walks the activated-bucket list when removing watched
paths. If a collision corrupts that list, some active directories can be
skipped and remain watched.

Track whether onas_ht_insert() allocated a new bucket, and only link the
bucket into ht->head/ht->tail when it is new. Colliding elements are still
inserted into the existing bucket without changing the bucket list.
2026-05-04 18:00:37 -04:00
Val S.
83c99570b0 Merge pull request #1717 from val-ms/CLAM-2976-uninitialized-zstream
Clam 2976 additional HFS+ parser improvements
2026-05-01 17:42:19 -04:00
Valerie Snyder
71732b999e Libclamav: harden HFS+ resource bounds checks
Malformed HFS+ metadata could overflow arithmetic in several
block and resource offset calculations before the code validated
those values. That left some bounds checks bypassable and could
redirect reads or seeks to the wrong offsets.

Add inline overflow guards before offset math, validate cmpf
resource headers against the extracted resource fork size, and
reject extents or block tables whose computed ranges exceed the
available data.

CLAM-2976
2026-05-01 17:41:38 -04:00
Valerie Snyder
c05c94978a HFS+: harden HFS+ cmpf resource parsing
The initial HFS+ cmpf fix stopped calling inflateEnd() on an
uninitialized stream, but the surrounding parser still had
three brittle spots: initialized zlib streams could bypass
cleanup on error paths, cmpf block tables were not bounded
against the resource length, and tmpname cleanup could loop
if unlink failed.

Tighten block-table validation using the cmpf resource length,
route cmpf block failures through per-block zlib cleanup, add
defensive cleanup to the inline decompression path, and make
tmpname unlink failures reportable without recursive cleanup.

CLAM-2976
2026-05-01 17:41:37 -04:00
Valerie Snyder
d36af7dfcd HFS+: avoid inflateEnd on uninitialized HFS+ cmpf streams
A crafted HFS+ cmpf resource block can take the uncompressed
path without initializing a zlib stream, but the block
cleanup still calls inflateEnd(). On our repro attempts this
produced a parser-local Z_STREAM_ERROR rather than a process
crash.

Initialize the z_stream defensively, track whether
inflateInit2() succeeded, and only call inflateEnd() for
initialized streams.

Credit: Mizu

CLAM-2976
2026-05-01 17:41:32 -04:00
sharkautarch
6c80437d13 clamonacc: fix OnAccessExcludePath issue
fix clamonacc onas_ddd_watch_hierarchy returning errors for recursively excluded paths that are children of an included path (#1710)
2026-04-30 06:52:25 -04:00
Val S.
a136d006b2 HFS+: Validate compressed attribute record bounds (#1708)
The HFS+ compressed-file attribute parser validated the attribute name
length as a UTF-16 character count, but later used that same field as a
byte offset by multiplying it by two. A crafted attribute record could
therefore place the inline attribute record header near the end of the
node and trigger an out-of-bounds read when ClamAV copied the record
header or payload.

Fix this by converting the attribute name length to a checked byte count
before using it in offset calculations. Validate that the inline
attribute record header fits in the node before reading it, and verify
that the claimed attribute payload also fits before copying it.

Credit: Sebastián Alba Vives

CLAM-2969
2026-04-27 16:38:04 -04:00
Val S.
a2e5b25275 Merge pull request #1715 from val-ms/update-generated-rust-bindings
Update generated Rust bindings
2026-04-27 11:42:25 -04:00
Val S.
9fe785d6ff Merge pull request #1686 from val-ms/CLAM-2957-generate-aes-key-optimization
Performance improvement generating key to decrypt read-only office docs
2026-04-15 17:25:51 -04:00
ipnerds
2c29eff332 Update sigtool.c to fix incorrect filename reference (#1702)
sigtool --testsigs takes two file references, while the file open code references the correct files, the error in the case of one file not being available was incorrect.
2026-04-13 11:56:14 -04:00
Valerie Snyder
e5f5464365 cmake: improve Rust sanitizer toolchain support
Improve the Rust build configuration used by sanitizer and fuzzing workflows.

This change adds three pieces of support:
- require a nightly Rust toolchain whenever `-Zsanitizer` is present in `RUSTFLAGS`, since Rust sanitizer support is unstable
- fail early when `-Zsanitizer=memory` is requested for an unsupported Rust target instead of surfacing a later Cargo ABI mismatch
- rebuild the Rust standard library with `-Zbuild-std` for MemorySanitizer so `core` and the rest of `std` use the same sanitizer ABI as the project crates
2026-03-18 18:09:44 -04:00
Valerie Snyder
ed956cc92e Performance improvement generating key to decrypt read-only office docs
The function `generate_key_aes()` required for creating a key for decrypting
velvetsweatshop encrypted files is really slow.

The main problem seems to be creating new openssl contexts in a loop rather than reusing
an existing context. Specifically, cl_sha1() is expensive per call.
Each cl_sha1() goes through cl_hash_data() (crypto.c (line 790)), which
allocates/initializes OpenSSL digest state every call (and on OpenSSL 3 also
creates/fetches provider context). Doing that 50k+ times is very costly.

CLAM-2957
2026-03-08 14:41:59 -04:00
Val S.
dad11f9b97 Bump the copyright year from 2025 to 2026 (#1667) 2026-03-07 14:18:17 -05:00
Val S.
1fede21819 Merge pull request #1683 from val-ms/CLAM-2924-win-crash-leave-temps-tempdir
Clam 2924 win crash leave temps tempdir
2026-03-05 12:06:55 -05:00
Val S.
8fc8e060af Fix possible panic when scanning some HTML files (#1682)
It is possible that invalid UTF-8 characters may trigger a Rust panic
(crash) when parsing CSS style blocks to extract images.

The issue is using `split_at()` instead of `split_at_checked()`.

I also found a few places where I could use string trim methods rather
than doing that logic manually.

Thank you to Krishnap7p for reporting this issue.

CLAM-2819
CLAM-2828
2026-03-04 16:31:13 -05:00
Valerie Snyder
e9f4ae1f09 Fix based on code review 2026-03-04 14:37:09 -05:00
Val S.
ee5b4d7867 Windows: Fix issue creating new temp subdirectory
On Windows, when scanning some files with `--leave-temps` enabled and
with `--tempdir` set to something like `C:\temp`, it may fail to create
a new subdirectory to store the temp files because the absolute file
path is too long for the `mkdir()` function.

The `mkdir()` function may fail on Windows if the filepath is longer than
the legacy MAX_PATH.
Fixing this in C or C++ is rather difficult, requiring either a registry
key + application manifest change, or else converting the path to UTF16
and UNC format (i.e. `"\\?\C:\temp"`) to pass to `CreateDirectoryW()`.

The solution in this commit is to use the Rust `std` library instead. It
is able to handle the longer file paths without issue.

CLAM-2924
2026-03-04 14:19:51 -05:00
Val S.
dcfe843880 Fix error handling when a scan fails to push a new embedded layer to the scan context
If pushing a new layer to the recursion stack in the scan context fails,
we need to restore the original recursion level, and undo any changes to
the convenience `ctx->this_level_...` convenience pointers.

This fixes a crash observed when scanning certain files on Windows with
`--leave-temps` enabled and also `--tempdir` set to "C:\temp".

CLAM-2924
2026-03-04 14:19:51 -05:00
Val S.
a0d6b638c2 Merge pull request #1668 from val-ms/CLAM-2942-CLAM-2941-CLAM-2930-cvd-verification-bugs
Clam 2942 clam 2941 clam 2930 cvd verification bugs
2026-03-02 16:33:04 -05:00
Val S.
256875a563 Fix pointer alignment issue in OLE2 XLM macro extraction (#1677)
Fix issue reading from a pointer which can cause a crash on systems that
have strict pointer alignment requirements.

Thank you to Hsuan-Ming Chen at Synology PSIRT for identify this issue
and proposing this fix.
2026-03-02 16:30:58 -05:00
Valerie Snyder
b9554a37ac Freshclam: Fix issue with CVDCertsDirectory when load-testing databases
Freshclam's feature to load-test a newly downloaded database is not using the
CVDCertsDirectory option to determine the certs directory.
The environment variable works, however.

In addition to the environment variable, you can work around the issue by
disabling load testing.

To fix this issue, we need to extend the libfreshclam API adding a
`fc_test_database_ex()` function that takes the certs directory as a
parameter.

Resolves: https://github.com/Cisco-Talos/clamav/issues/1630

CLAM-2930
2026-02-20 15:53:46 -05:00
Valerie Snyder
6f55c0de57 Freshclam: Fix CLD verification bug with PrivateMirror option
There is a bug affecting ClamAV 1.5.0 and 1.5.1 where it attemps to
download the .sign file and verify the .sign or legacy RSA digital
signature for CLD files when using the PrivateMirror option.

For context, the PrivateMirror option enables you to download either
CLD or CVD files from a mirror such that you can serve a private mirror
where the signatures are pulled using Freshclam.
Note that it is better to use the CVDUpdate utility which always serves
digitally signed CVD and CDIFF files. The PrivateMirror capability
predates CVDUpdate and is still used by many today.

Resolves https://github.com/Cisco-Talos/clamav/issues/1626

CLAM-2941
2026-02-20 15:53:46 -05:00
Valerie Snyder
fb7b5784cc Ignore cert files in CVD certs directory which can't be read
The default CVD certs directory on unix systems is `/usr/local/etc/certs`, which
is not unique to ClamAV and may already exist and include other certificates,
some of which may have restricted user permissions inaccessible to the running
ClamAV application. In this scenario, ClamAV should skip over the cert files it
cannot read.

Resolves: https://github.com/Cisco-Talos/clamav/issues/1665

CLAM-2942
2026-02-20 15:53:45 -05:00
Val S.
1b55785e22 Freshclam: don't force proxy tunneling (#1664)
Resolves: https://github.com/Cisco-Talos/clamav/issues/179

Thank you to ccamachofg and zerodeux for identifying the solution.

CLAM-2936
2026-02-20 15:48:21 -05:00
Val S.
696424ef36 Windows: Fix unit tests with pure text PDF file (#1671)
Git performs newline conversions on plain text files.
Modify the .gitattributes files to prevent that for PDF files.
2026-02-20 15:25:44 -05:00
Dmitriy Alekseev
dfcf0387af feat: add SELFCHECK command and related configuration options (#1551)
Add SELFCHECK command and related configuration options

Document SELFCHECK command in clamd.conf.sample.
Document EnableSelfCheckCommand in clamd.conf.
Implement robust SELFCHECK test with retries.
Added robust SELFCHECK test to handle RELOADING state.
2026-01-29 15:27:43 -05:00
John Humlick
b624871cbc libclamav: Malformed regexes result in misleading memory error messages. (#1635)
The regex parsing code treated anything that did not return CL_SUCCESS
as CL_EMEM in several places, resulting in a return code indicative of a
malformed database returning a memory error instead. This change passes
the real return code up the chain, and also prevents trying to realloc 0
bytes when we don't have anything to realloc due to a malformed
database.

CLAM-2191
2026-01-21 12:17:14 -05:00
John Humlick
17f74cf2f3 libclamav: Add PDF stats for metadata collection. (#1546)
More PDF statistics were requested for feature parity.
If metadata collection is enabled, the following additional PDF
statistics will be collected:
  - Number of Automatic Actions
  - Number of Streams
  - Number of Objects
  - Number of Object Streams
  - Number of Trailers
  - Number of URIs
  - Number of Xrefs

Additionally, some of the parsing logic was fixed during testing of
these features.

CLAM-2820
2026-01-21 12:13:01 -05:00
John Humlick
fa83ece937 Add support for real-domain-only phishing allow list signatures. (#1607)
Add support for Y-type signatures in wdb files.
There are some cases where it is desired to allow a single domain to
have any displayed address and not count that as phishing. An example of
this would be the domain for outlook URL checker, or Google safe
browsing. If a wdb file contains a Y type entry only the real domain
will be matched, not the real and displayed domain.

CLAM-2426
2026-01-14 08:55:41 -05:00
John Humlick
4361c25030 libclamav: Remove MyDoom Heuristic (#1545)
The MyDoom heuristic has been causing too many false positives.
Since we already have MyDoom coverage through signature detection, the
hard-coded heuristic that causes many false positives is no longer
needed. This commit removes the hard-coded heuristic.

CLAM-2766
2025-12-17 12:10:12 -05:00
Jonas Zaddach
cb844d3897 CMake: Add win32_compat dependency to libraries using pthread.h (#1520) 2025-12-16 14:24:22 -05:00
Val S.
1a739051ea Merge pull request #1518 from zaddach/simplify_windows_install
Allow Windows install() to use GNUInstallDirs structure
2025-12-15 16:17:32 -05:00
Jonas Zaddach
661826d468 Tests: Fix Windows compatibility with testing example programs
Don't concatenate pythonpath and str

Fix test program path for Windows Ninja Multi-Config

Use environment variable to pass cl_cvdunpack_test location to test

Use ENABLE_EXAMPLES instead of ENABLE_TESTS to gate ex_cl_cvdunpack

Directly use the target's path on Windows

Also change the program finding for ex_scan_callbacks_test

Fix python paths handling

Fix the order of some expected results which were incorrect and for
some reason only failed when tested on Windows.
This final fix in this commit provided by Val Snyder.
2025-12-15 14:14:08 -05:00
Jonas Zaddach
d479ebbf6a Remove ex_prescan_callback and ex_file_inspection_callback examples
The prescan and file_inspection callbacks are deprecated and should not be used.
They are replaced by a more unified scan callback system which is demonstrated in
ex_scan_callbacks.c.
2025-12-15 14:14:08 -05:00
Jonas Zaddach
39ca12e136 Remove ZEXTERN and EXPORT from internal functions
In inflate64.c on Windows, as zlib.h is included,
it sets ZEXTERN to " __declspec(dllimport)". In consequence,
our internal functions have the wrong linkage and linking fails
because of the missing dll functions.
2025-12-15 14:14:08 -05:00
Jonas Zaddach
7c222f4a12 CMake: Support finding the OpenSSL library paths provided by vcpkg 2025-12-15 14:14:07 -05:00
Jonas Zaddach
cc71c0db1e CMake: Support finding the check library as published by vcpkg 2025-12-15 14:14:07 -05:00
Jonas Zaddach
75047180ee GitHub Actions: Fix Windows workflow
Build on windows-2022, as windows-2019 is no longer available

Use updated vcpkg github action

Try to use vcpkg manifest mode

Provide vcpkg baseline commit hash

Correctly request dependency feature

Fix printing vcpkg triplet

Try building with CMakePresets.json
2025-12-15 14:13:59 -05:00
Jonas Zaddach
f738133e8e CMake: Simplify install on Windows
The install BINDIR, SBINDIR, LIBDIR, and INCLUDEDIR may be set in
the top level CMakeLists.txt and does not need to be set for each
target. This also enables a build to customize those so that the
bins COULD go to the "bin" directory.

Also add CMake option "ENABLE_WINDOWS_INSTALL_THIRDPARTY_DEPENDENCIES".
- When enabled (default), the install will include required system runtime
  libraries and also a copy of the other third party library dependencies
  (e.g. libpcre2, libxml2, libcrypto, etc.).
- When disabled, those files are not included.
  One situation where this is useful is if vcpkg is being used to build
  ClamAV itself (including its dependencies).
2025-12-12 18:46:45 -05:00
Kaan Yagci
c73755d3fc docs: update README.Docker.md (#1629)
Fix the broken Docker registry link
2025-11-06 16:08:45 -05:00
Val S.
ee59e9b630 Fix typo in Linux cross-compile instructions (#1614)
BZIP2_LIBRARY should actually be BZIP2_LIBRARY_RELEASE
or else BZIP2_LIBRARIES

Resolves: https://github.com/Cisco-Talos/clamav/issues/1611
2025-10-22 14:04:54 -04:00
Val S.
8475d4e658 Merge pull request #1599 from Cisco-Talos/CLAM-2882-dll-scan-performance
Several fixes: ZIP alert-exceeds-max, OOXML properties, PE scan and other performance issues
2025-10-15 15:37:53 -04:00
Val S.
4d45c0ac2e Valgrind suppression for false positive in Rust png-decoder crate 2025-10-14 22:34:53 -04:00
Val S.
50326da519 Fix embedded RAR archive extraction issue
If the current layer has a file descriptor, ClamAV is passing the path
for that file to the UnRAR module, even if the RAR we want to scan is
just some small embedded bit (e.g. detected by RARSFX signature).

We need to drop the RAR portion to a new file for the UnRAR module
because it does not accept file buffers to be scanned, only file paths.

CLAM-2900

Note this commit also changes `scanners.c` to use `access()` on Windows
instead of `_access_s()`. ClamAV defines `access()` to map to a custom
`access_w32()` function on Windows. We already use it everywhere else.
2025-10-14 18:23:56 -04:00
Val S.
b1c1f1840c Update Rust dependencies; Fix image fuzzy hash values
Large range testing identified some files where image fuzzy hashing
produces different hashes with ClamAV 1.5 vs 1.4.

With my investigation, I found the issue is with changes in Rust library
dependencies, though it actually wasn't any change with the 'image' or
'jpeg-decoder' crates. After running a simple `cargo update` to update
all non-pinned versions.
I confirmed that this does not affect the minimum supported Rust version
(MSRV).

CLAM-2899
2025-10-14 14:05:13 -04:00
Val S.
1a2515eea9 Fix compiler warning
Mismatched declaration and definition.
2025-10-14 14:05:12 -04:00
Val S.
0462dae12a Increase limit for finding PE files embedded in other PE files
I am seeing missed detections since we changed to prohibit embedded
file type identification when inside an embedded file.
In particular, I'm seeing this issue with PE files that contain multiple
other MSEXE as well as a variety of false positives for PE file headers.

For example, imagine a PE with four concatenated DLL's, like so:
```
  [ EXE file   | DLL #1  | DLL #2  | DLL #3  | DLL #4 ]
```

And note that false positives for embedded MSEXE files are fairly common.
So there may be a few mixed in there.

Before limiting embedded file identification we might interpret the file
structure something like this:
```
MSEXE: {
  embedded MSEXE #1: false positive,
  embedded MSEXE #2: false positive,
  embedded MSEXE #3: false positive,
  embedded MSEXE #4: DLL #1: {
    embedded MSEXE #1: false positive,
    embedded MSEXE #2: DLL #2: {
      embedded MSEXE #1: DLL #3: {
        embedded MSEXE #1: false positive,
        embedded MSEXE #2: false positive,
        embedded MSEXE #3: false positive,
        embedded MSEXE #4: false positive,
        embedded MSEXE #5: DLL #4
      }
      embedded MSEXE #2: false positive,
      embedded MSEXE #3: false positive,
      embedded MSEXE #4: false positive,
      embedded MSEXE #5: false positive,
      embedded MSEXE #6: DLL #4
    }
    embedded MSEXE #3: DLL #3,
    embedded MSEXE #4: false positive,
    embedded MSEXE #5: false positive,
    embedded MSEXE #6: false positive,
    embedded MSEXE #7: false positive,
    embedded MSEXE #8: DLL #4
  }
}
```

This is obviously terrible, which is why why we don't allow detecting
embedded files within other embedded files.
So after we enforce that limit, the same file may be interpreted like
this instead:
```
MSEXE: {
  embedded MSEXE #1:  false positive,
  embedded MSEXE #2:  false positive,
  embedded MSEXE #3:  false positive,
  embedded MSEXE #4:  DLL #1,
  embedded MSEXE #5:  false positive,
  embedded MSEXE #6:  DLL #2,
  embedded MSEXE #7:  DLL #3,
  embedded MSEXE #8:  false positive,
  embedded MSEXE #9:  false positive,
  embedded MSEXE #10: false positive,
  embedded MSEXE #11: false positive,
  embedded MSEXE #12: DLL #4
}
```

That's great! Except that we now exceed the "MAX_EMBEDDED_OBJ" limit
for embedded type matches (limit 10, but 12 found). That means we won't
see or extract the 4th DLL anymore.

My solution is to lift the limit when adding an matched MSEXE type.
We already do this for matched ZIPSFX types.
While doing this, I've significantly tidied up the limits checks to
make it more readble, and removed duplicate checks from within the
`ac_addtype()` function.

CLAM-2897
2025-10-14 14:05:12 -04:00