Conversation
Merge master branch into develop (zonemaster-engine)
The IP address bound to a.root-servers.net is now in over 30 ASNs simultaneously, so let’s use K-root instead, whose address is still in one AS. Until we find a better way.
Parts of this unit tests relies on live data from the Internet that cannot be guaranteed to stay the same. As of now (2026-03-25), the data on www.wiccainfo.se cannot be recorded anymore. These parts are essentially made obsolete by t/recursor-A.t, which exercises the Zonemaster::Engine::Recursor much more thoroughly by means of the test scenario framework. However, we cannot delete the entire file without negatively affecting test coverage in some small parts of the codebase. Best to be careful and not just go around deleting too many things in one go.
Whoever owned 001.tf dropped the domain, but fortunately 001.re exists and has the same problem, namely having all its name servers in the same AS.
Thanks to scanning the entire .fr zone with Zonemaster, I was able to find other domains that had the same problems as those that were previously in the test file, even removing a TODO block in the process.
Two unit tests, t/Test-zone01-{A,B}.t, had incorrect fake delegations
that prevented correct rerecording of the unit tests, given how the
zones are currently set up.
And in t/undelegated.t, an update was necessary for the fake delegations
so that they’d trigger FAKE_DELEGATION_IN_ZONE_NO_IP again.
The reason why t/undelegated.t needed fixing is not quite clear to me
yet. It might be because in the real world, the name servers names of
nic.se are no longer all subdomains of nic.se.
At the end of t/nameserver.t, there are attempts to send queries to a fake nameserver whose IPv4 address lies in 192.0.2.0/24 (TEST-NET-1), a range that should not be routable on the public Internet, in order to elicit a guaranteed resolution failure. However, the test is flawed and should only work when it is run under ZONEMASTER_RECORD=1. Here’s why. The test expects a resolution failure to generate two messages, a LOOKUP_ERROR message and a BLACKLISTING message. However, looking at the logic in Zonemaster::Engine::Nameserver, these messages are only generated if the query was actually sent out on the network; in other words, if the Nameserver object is returning a cached resolution failure, these messages will not be generated. Therefore, if running offline (without ZONEMASTER_RECORD=1), we *should not* have these two messages and their presence arguably indicates a bug with the cache. Because of that flawed logic in t/nameserver.t, after rerecording the t/nameserver.data file with: $ ZONEMASTER_RECORD=1 prove -l t/nameserver.t then running the test again in offline mode with: $ prove -l t/nameserver.t the test stops passing. This commit changes the test’s logic so that if we run offline, we ensure that LOOKUP_ERROR and BLACKLISTING are *not* generated. The previous logic is only run if running with ZONEMASTER_RECORD=1.
The latest version of Perl is now 5.42. Let’s bump the topmost version in the list of Perls tested against in CI to that.
…enance Update unit tests depending on real-world data
Update DNSSEC10 implementation
Add a small function in Zonemaster::Engine::Util named “escape”, that can be used for escaping non-ASCII or non-printable characters in strings so that they do not cause problems. The code trades off some space and some style for significant speed improvements compared to more naive solutions. On my machine, the code handles 1 million strings in 2.468 s (down from 9.527 s in the first iteration).
The TXT resource records we obtain in version.bind and version.server/TXT/CH queries are byte strings and can contain all sorts of funny things, including terminal control characters, HTML injection attempts, invalid UTF-8 byte sequences and every octet under the sun. If we are logging and displaying this data in user interfaces, it better be sanitized somehow, or bad things can happen. Because we are a DNS testing tool, we can simply turn these strings into the well-recognized presentation format specified in RFC 1034 and 1035, replacing any byte outside of the printable ASCII range (decimal 32–126) by its backslash-decimal number sequence (e.g. ESC, or ASCII 27 decimal, becomes \027), and turning backslashes into the double-backslash (\\) escape sequence. As a drive-by change, we also fix a small logic error that appears a few lines down. The intent is to check if the string is non-empty, but the faulty logic meant that a string containing a single zero is also considered falsey.
Perls before 5.28 disallow initializing list variables as state variables, which is what escape() uses for a lookup table for escape codes. As a workaround, we use a lexically-scoped table and the escape() subroutine closes over the table. This commit can be reverted cleanly if we drop support for Perl 5.26.
The latter is a better name for the function in Zonemaster::Engine::Util.
…ening Harden Nameserver15 against creative version strings
Parameters are normalized to ensure that the cache is hit for semantically identical queries.
We’ve migrated cache file formats in a previous commit, so we can remove all the temporary code that was there to support migration from old to new format, and thus complete the job.
Switching from JSON to CBOR for the cache format has made the need for a TO_JSON method in Zonemaster::Engine::DNSName and …::Packet unnecessary. We can now remove these methods.
This script will be much more useful after the format change, because we are switching to a binary format instead of a vaguely text-based one.
Rewrite the axfr() method in Zonemaster::Engine::Nameserver so that it
goes through the cache like query() would.
Implementing this change is a bit more difficult because the API for
AXFR requests in Zonemaster::LDNS is very different from that of
non-AXFR queries.
The basic idea is to use a synthetic AXFR query packet as a cache key,
and to create another synthetic response packet that stores the RRs that
were fetched through the AXFR query (as long as the provided callback
returns 1). That packet is then inserted into the cache. When loading
the cache, the axfr() uses that saved synthetic packet to simulate an
AXFR query.
Interestingly, the t/nameserver-axfr.t test file uses its own data file
format. It actually implements a cache of its own. This is not necessary
anymore and this commit amends the .t file to put it in line with the
others.
There is however one subtlety that I couldn’t fit into the design of the
synthetic answer packets in case the AXFR fails, because it requires a
new feature in Zonemaster::LDNS.
In order to test this commit:
1. Using zonemaster-cli, run the Nameserver03 test on your favorite
domain while saving the packets, e.g.:
$ zonemaster-cli --save mydata --test nameserver03 servfail.fr
2. Examine the cached packets using the data2dig script in the util
subdirectory in Zonemaster-Engine, and look for cached AXFR queries
in the output:
$ ./util/data2dig mydata | grep AXFR
AXFR responses, including errors, are cached as synthetic packets thanks to previous work. But we had no elegant way of storing the associated error message. It felt appropriate to use an extended DNS error code 13 (Cached error) for that purpose, so after implementing the missing feature in Zonemaster::LDNS, we can use it here.
Replace Perl INIT block with explicit initialization
Overhaul saved packets’ serialization format
Add a test that exercises the code that converts log entries into JSON format.
This reverts commit bb5ddfb. It turns out that these methods weren’t obsolete after all. In particular, the removal of the TO_JSON method in Zonemaster::Engine::DNSName caused some issues that weren’t caught in unit tests. If you run: $ zonemaster-cli --level info --test basic02 --no-ipv6 \ zonemaster.net --json | jq you should see that on the second message, the "domain" argument is a domain name, and no longer "null".
Revert "Remove obsolete TO_JSON methods"
Add artifact build to the CI
CI: Target Perl version 5.42
CI: force update
Remove deprecated profile properties for v2026.1 release
Update French translation
Updates Swedish translation after update of the msgids
Updates for release v2026.1 (Engine)
Adds missing tag in list of tags for DNSSEC10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
This PR is step https://github.com/zonemaster/zonemaster/blob/develop/docs/internal/maintenance/ReleaseProcess-release.md#15-merge-develop-branch-into-master
How to test this PR
"No reviewer or approval is required for this update."