Download Latest Version v9.0.0 source code.zip (46.6 MB) Google Add to Preferred Sources
Home / v9.0.0
Name Modified Size InfoDownloads / Week
Parent folder
zeek-9.0.0.tar.gz 2026-09-14 100.7 MB
zeek-9.0.0.tar.gz.asc 2026-09-14 870 Bytes
README.md 2026-09-14 20.1 kB
v9.0.0 source code.tar.gz 2026-09-14 40.9 MB
v9.0.0 source code.zip 2026-09-14 46.6 MB
Totals: 5 Items   188.2 MB 21

We'd like to thank Aaron J. Scantlin (@scantlina), @airshelley, Alexey Rubanik (@Rubanik-Alexei), Azil (@achill06), Bauti Peirone (@bautipeirone), Blair McCormick (@blairSmcc03), Craig Leres (@leres), Craig P (@detection-labs), @Cxiyuan, Dragon Roar (@lczllx), @eb-anssi, Eduardo Kohn (@eagle-head), Eldon Koyle (@ekoyle), @franky-m, Jan Grashöfer (@J-Gras), Javid Khan (@dxbjavid), Jie (Link) Zheng (@chillancezen), @jmestwa-coder, Julio César Suástegui (@juliosuas), Keith J. Jones (@keithjjones), Kevin Harrington (@ke5C2Fin), Maor Hamami (@mamaorha), Mario D (@mari0d), Matthias Vallentin (@mavam), Mohan Dhawan (@mdhawan, @Mohan-Dhawan), neil (@neilpang), Otto Fowler (@ottobackwards), Peter Cullen (@pbcullen), Seth Grover (@mmguero), Shubham Kumar (@chmodshubham), Simeon Miteff (@simeonmiteff), Smoot (@stevesmoot), Stefan Götz (@stefangoetzcorelight), Steven (@malvidin), Sujala Vasanthasena Nelavai (@sujalavnelavai), Swastik Bose (@VasuBhakt), @tim-cyb, Urval (@urvalkheni), @uwezkhan and Yacin Nadji (@ynadji) for their contributions to this release.

In addition, we're grateful to Kara Zaffarano and Kyle Elliott of Trail of Bits in collaboration with OpenAI, AdaLogics in collaboration with Anthropic, and the Canadian Communications Security Establishment for their code-scanning efforts and resulting bug reports.

Breaking Changes

  • Expanding on the removal of Broker::listen_websocket() in Zeek 8.1, this release fully removes Broker's legacy embedded WebSocket server. The script layer no longer provides Broker::BrokerProtocol and the options Broker::default_port_websocket, Broker::default_listen_address_websocket, Broker::web_socket_buffer_size, and Broker::web_socket_overflow_policy have likewise been removed. Use :zeek:see:Cluster::listen_websocket() and the ZEEK_WEBSOCKET_* environment variables instead.

In Zeek's core, the Broker manager's Listen() method now always uses Broker's native protocol and no longer accepts the optional BrokerProtocol argument. The BrokerProtocol enum has been removed.

  • Calling the zeek::util::fmt() helper function from non-main threads will now emit a warning of the following form once:

    zeek::util::fmt() called off the main thread; use threading::BasicThread::Fmt() or std::format()

In a debug build, Zeek will also abort. If you see above message, it is likely that an installed plugin spawned a thread and uses the API wrongly (likely input or logging threads). When deploying custom plugins, you should optimally test Zeek and all plugins separately with the thread and address sanitizers enabled (./configure --sanitizers=thread or ./configure --sanitizers=address).

  • The ZeekJS plugin now requires std::format from C++20 which is not available in older distributions using GCC 12.x like Debian 12. If you want to use JavaScript support in Zeek, please update to a more recent distribution.

  • Beginning with Zeek 9.0, the Zeek team is sunsetting our official support of FreeBSD. This is primarily because of our move to a new CI provider and the lack of good support for FreeBSD. We are moving FreeBSD support to the same model as OpenBSD where we will accept patches from external contributors if we break something, but not build and run the test suite on FreeBSD ourselves. This will simplify our maintenance a bit, as well as reduce the amount of time spent on CI jobs.

New Functionality

Instead of reading raw packets from a network interface, this packet source turns Zeek into a UDP server to process UDP-based VXLAN or GENEVE mirror traffic directly:

zeek -i udp::0.0.0.0:4789:vxlan

The listening UDP socket is opened using the SO_REUSEPORT socket option. When scaling the number of Zeek workers, the kernel will balance packets among the individual UDP sockets based on the hash of the outermost UDP headers.

This packet source comes with a few ConnKey implementations to make connection tracking aware of VXLAN VNI and GENEVE VNI. This feature needs to be explicitly enabled by loading one of the corresponding policy scripts, for example:

zeek -i udp::0.0.0.0:4789:vxlan policy/frameworks/conn_key/packet_source/udp/vxlan_vni

To disable building the packet source, use:

./configure -D ENABLE_PACKET_SOURCE_UDP=no

While the zeek-systemd-generator is Linux and systemd specific, the zeek.conf file (and the code reading the file) are meant to be operating system agnostic and we're open for suggestions and contributions for alternative generators.

  • The LDAP analyzer now forwards the SASL payload from bindRequest and bindResponse units to GSSAPI and NTLM parsers to extract additional information into the the ntlm.log or kerberos.log logs.

  • The Syslog analyzer has been extended to support TCP using Octet Counting and Non-Transparent-Framing, registered on port 514/tcp by default.

  • Escaping of control characters and invalid UTF-8 sequences for JSON logging has been made configurable. See the updated ASCII writer's online documentation for more details:

    https://docs.zeek.org/en/master/frameworks/logging.html#json-and-binary-data-in-strings

To change the escaping behavior globally, redefine the new LogAscii::json_string_escape_policy:

redef Log::json_string_escape_policy = JSON::STRING_ESCAPE_POLICY_TSV;

The default behavior continues to be JSON::STRING_ESCAPE_POLICY_HEX which can result in non-reversible encodings. Discussion [#5240] on GitHub has a lot more details on the topic: https://github.com/zeek/zeek/discussions/5240

  • The Input Framework now supports reading pattern values containing case-insensitive and single-line modifiers (/foo/i, /bar/s or /foobar/is).

  • Imported the zeek/spicy-zip file analyzer into the main tree. This analyzer outputs information about ZIP files found in other protocols, including information about the contents of such archives. It will recursive search zip files, so there is the possibility of long chains. The maximum depth can be controlled via the Spicy::max_file_depth variable.

The analyzer is not registered for any MIME types by default due to the potential for ZIP analysis to take very long times. This may prevent Zeek from doing other work. A new policy script policy/files/zip/register.zeek can be loaded to map the ZIP analyzer to the application/zip MIME type.

  • Added a policy script policy/protocols/conn/multicast-participants.zeek. This script writes a new multicast_participants.log that contains information about multicast connections with data about the participating hosts collected from IGMP.

  • The script_id records returned by the global_ids() BiF now include information about the attributes attached to identifiers in the $attributes field.

  • The event ssl_extension_signature_algorithms_cert was added. It is raised for the signature_algorithms_cert TLS extension.

  • The new ?as operator evaluates to true if Zeek can safely convert its lefthand operand to its righthand type. This change accompanies expanded support for the as casting operator, see below.

  • The event ssl_extension_encrypted_client_hello was added. It contains information about the encrypted_client_hello TLS extension.

  • Added two new NTP logs: ntp_control.log and ntp_private.log, corresponding to NTP modes 6 and 7. Since these modes differ from other NTP operations, they were added to separate logs. Previously, only NTP modes 5 and under were logged.

  • Added DPD signatures for QUIC version 1 and QUIC version 2 to attach the QUIC analyzer on non port 443 UDP connections when there's a signature match.

  • The kerberos.log log entries now contains AP entries with filled service and cipher columns. Previously, the log entries had all columns unset.

  • The krb_ap_request() event was extended with an in_kdc_padata parameter to recognize if the corresponding AP-REQ is contained within KDC/TGS pre-authentication data.

  • A new event dce_rpc_auth() was added for script-level access to the selected security provider, per-message protection and authentication context contained in DCE-RPC PDUs.

  • The OpaqueType class has been made non-final and extended with hooks for hashing, casting and default initialization. This allows adding new scripting types that may be stored in sets or tables and casted to existing Zeek types, something that wasn't previously possible without introducing BIF functions. While the OpaqueType class isn't in the zeek::detail namespace, deriving and implementing the new hooks is considered experimental and not subject to the usual deprecation policies.

  • A new Reporter::limit_reached_weird BIF was added for reporting cases where a size limit was reached. This is typically used in security patches to ensure that memory limits are not being exceeded. The BIF reports a named weird and adds a X to the connection's history field when the connection is available.

Changed Functionality

  • The known-certs, known-hosts, and known-services scripts had options added to support using the storage framework instead of broker stores, which are slated to be removed in v9.1. For example, a new option was added for the hosts script called enable_hosts_persistence for enabling the storage framework. Options for controlling the framework were also added: host_store_prefix, host_store_backend_type, and host_store_backend_options. By default it uses an SQLite backend, with the file stored in a directory under Cluster::default_store_dir. Similar options are available for certs and services as well.

  • The extension_signature_algorithm event previously was incorrectly raised when a CertificateRequest message was encountered. It now is not raised for CertificateRequest messages.

  • The proposed HTTP QUERY method from RFC 10008 does not produce a weird anymore. Zeek already parsed the QUERY method, but raised a weird.

  • The HTTP analyzer was extended with a number of new weirds to detect unusual Content-Length, Transfer-Encoding and Expect header usage:

    HTTP_bad_chunk_size HTTP_chunked_multi HTTP_content_length_0_and_expect_100_cont HTTP_content_length_leading_zeros HTTP_bad_content_length HTTP_obsolete_line_folding HTTP_content_length_and_chunked HTTP_content_range_and_chunked HTTP_expect_not_100_continue

If you observe an excessive number of these weirds, you may always filter these out or report as false positives to us.

  • The options and redefinitions from zeromq/main.zeek were split into a separate file zeromq/options.zeek to enable standalone Zeek processes connect to the ZeroMQ layer, without partaking in cluster node events.

  • The as operator now supports all of the type conversions currently available via explicit conversion BiFs (such as interval_to_double() and similars), plus some additional ones that are natural companions. See the type-casting section in the operator documentation for details. Zeek's own scripts now use as throughout.

  • policy/protocols/ssl/ssl-log-ext.zeek now logs the HPKE KDF and AEAD identifiers from the encrypted client hello extension in the ech_kdf_id and ech_aead_id fields.

  • The software framework features improved control over version findings. The existing parse cache, mapping unparsed versions to Software::Version records, now supports configurable expiration times via the Software::parse_cache_interval setting.

A new deduplication cache filters versions on the workers, preventing repeated reporting of the same version. This cache's lifetime is configurable via Software::found_cache_interval, defaulting to 10 minutes. To disable the cache and restore historical behavior, redefine this value to 0secs.

On the proxy nodes, tracking of software versions now keeps a day-long history of versions encountered on a given host, further deduplicating log writes. The Software::max_software_cache_size tunable caps the size of this per-host, per-software history. Redefining this setting to 0 disables this cache.

  • The buffering state of a logging stream set via Log::set_buf() is now inherited by writers created dynamically at runtime after the Log::set_buf() call.

  • Setting Log::flush_interval to 0.0sec now disables the flushing timer for log streams. Previously, it would result in scheduling a new timer that would immediately expire, something that isn't very useful.

  • Certain protocol fields in the RDP parser are capped to maximum values to prevent unbounded buffering. This also prevents signed integer overflow reports from the BinPAC-generated code when running under UBSAN.

  • The local.zeek script no longer loads policy/frameworks/telemetry/log.zeek by default.

  • Previously, Zeek wouldn't log FTP sessions that only had USER/PASS/QUIT commands in ftp.log at all. This has been changed to log at least one command (the last one) when no other command was logged for the session, even if that command isn't part of FTP::logged_commands. You can revert to the previous behavior by setting FTP::log_at_least_one_command=F.

  • Added a recursion limit to Zeek script function calls. This will trigger a runtime error if the number of nested function calls exceeds the limit. This also adds two new BiFs: set_max_recursion_depth to set the maximum number of function calls, and get_max_recursion_depth to get that limit. Should the limit be set to 0, the check is skipped, reverting to previous (unchecked) behavior.

  • The RPC analyzer resets its internal tracking table for RPC calls when more than rpc_max_pending_calls (default 1000) calls are pending to prevent unbounded state growth. This includes freeing the RPC_CallInfo values. The RPC analyzer (used by the NFS and MOUNT analyzers) is not enabled in a default configuration.

  • DNS messages sent to multicast destinations (i.e. mDNS and LLMNR) are no longer associated as query/response pairs, since replies for these protocols arrive on different connections than queries. Each multicast message now produces its own independent log entry. This may result in more dns.log entries for environments with multicast DNS traffic, but the previous paired entries contained data from unrelated messages and were not valid. To revert to the previous behavior: redef DNS::multicast_subnets = {};

  • The bifcl compiler can now split the generated functions into a shim with the traditional calling sequence, and a new native function that takes and returns C++ values. The shim does standard checking on the Args vector, converts its ValPtr objects to C++ values (as before), calls the native function, and converts its return value back to a ValPtr. This simplifies writing BiFs and allows script optimization to directly call the native functions without going through the shim.

This change is not backward-compatible, so bifcl only makes the split for source files that include a %gen-native directive. All .bif files in the Zeek tree do so and have been converted to the native format.

  • Multiple weirds associated with configurable limits will now mark the connection history with 'X' if Zeek will stop processing traffic after the limit was hit. This is in line with other, similar weirds.

  • The unknown_protocols.log previously included the IP next protocol field as a 16 bit value, with the first byte value set to the next protocol followed by a zero byte due to a spurious use of htons(). This has been fixed to be just the next protocol byte.

  • The kerberos.log was updated to set the client column to /<realm> for AP requests that do not otherwise carry a client name.

  • The success column of the kerberos.log is now updated to T when an AP-REP is observed.

  • AP-REQ contained with KDC/TGS pre-authentication are now ignored for purposes of logging to kerberos.log.

  • Fixed file descriptors of the WebSocket server and WebSocket client connections (Cluster::listen_websocket()) being inherited by child processes. E.g., when using system() in Zeek scripts or the Input Framework's raw reader functionality.

  • The LDAP analyzer now limits the number of pending request and search messages for correlation to a configurable limit (default 10) to prevent unbounded state growth. When reached, all pending requests and messages will be flushed and logged and one of the new weirds LDAP_max_pending_messages_exceeded or LDAP_max_pending_searches_exceeded raised.

  • The number of data channels per worker is now capped at a configurable maximum FTP::max_expected_data_channels (default 100000). When the limit is reached, FTP data connection correlation across a Zeek cluster is disabled to prevent unbounded state growth and cluster overload until expiration removes old entries.

  • A UDP Spicy analyzer which replaces a Zeek analyzer will now error instead of crashing if it sees TCP traffic. This is possible for DNS, including the spicy-dns analyzer (which is an optional, separate component from Zeek).

  • Broker's IdentifierUpdate messages are now disabled by default, to prevent one class of unintended runtime updates to Zeek configuration settings. Zeek drops attempts to send or receive such messages and triggers reporter errors. The new Broker::enable_identifier_updates toggle, defaulting to false, controls the behavior. Consider using the config framework instead of re-enabling identifier updates.

Deprecated Functionality

  • The Broker messaging backend is now deprecated. ZeroMQ has been the default cluster messaging backend used by zeekctl since Zeek 8.1, and we encourage everyone to switch their clusters over to ZeroMQ at this time. We are not going to remove Broker with 9.1, but Broker will become a build-time opt-in feature over the course of the 9.x cycle and likely see removal in 10.1.

Third-party applications should focus on Zeek's WebSocket stack for connecting into the Zeek cluster, while JavaScript offers support for reaching out to HTTP APIs from Zeek scripts.

  • Development of the Management Framework has been discontinued and its scripting code will be moved into an external package with Zeek 9.1. If you've been deploying Zeek clusters using the Management Framework, you can continue to do so with Zeek 9.0, but should consider moving to ZeekControl, or preferably explore the newer zeek.conf and zeek-systemd-generator approach.

More details and background on this decision are available on the Zeek blog:

https://zeek.org/2026/08/beyond-zeekcontrol/
  • The SSL::hash_algorithms and SSL::signature_algorithms tables have been deprecated. They are outdated with TLS 1.3, and not used in Zeek. If you currently use these tables, you should switch to your own copy of the IANA tables and consider also using the TLS SignatureScheme IANA table.
Source: README.md, updated 2026-09-14