{"id":586,"date":"2026-10-15T22:14:09","date_gmt":"2026-10-16T05:14:09","guid":{"rendered":"https:\/\/blog.canutethegreat.com\/?p=586"},"modified":"2026-11-07T18:11:02","modified_gmt":"2026-11-08T02:11:02","slug":"horcrux-dev-log-4-nightly-tests-and-a-nas-login-that-accepted-any-password","status":"publish","type":"post","link":"https:\/\/blog.canutethegreat.com\/index.php\/2026\/10\/15\/horcrux-dev-log-4-nightly-tests-and-a-nas-login-that-accepted-any-password\/","title":{"rendered":"Horcrux dev log 4: nightly tests, and a NAS login that accepted any password"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><em>Part 4 in the Horcrux dev log series.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Backdated: written in November 2026 from git and CI records. <a href=\"https:\/\/blog.canutethegreat.com\/index.php\/2026\/09\/30\/horcrux-dev-log-3-back-after-nine-months-92-failed-ci-runs\/\">Part 3<\/a> ended with CI finally running.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On October 4 a nightly workflow went in that boots an actual VM (CirrOS) and runs real container and CNI network tests. On the 7th a stress suite followed, with workers logging in and hammering the API. Both run on my own runners.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">119 commits in the fortnight. From the Forgejo API for October 1 to 15:<\/p>\n\n\n\n<pre tabindex=\"0\" class=\"wp-block-code\"><code>all workflows: 233 runs (140 success, 68 failure, 18 cancelled)\nci.yml: 53 success, 43 failure, 13 cancelled\nnightly-realistic-test: 18 success, 17 failure\nnightly-stress-test: 14 success, 3 failure<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">About half the realistic nightlies failed. I haven&#8217;t broken those 17 failures down by cause, but the boot timeout was one of them. The VM boot deadline was 120 seconds and the runners are TCG-only (no KVM), so a commit on the 8th raised it to 240. On the 15th the commit message says &#8220;was never enough&#8221;.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The CNI bugs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The commit on October 4 says the nightly tests caught two real bugs in CNI and container handling that day, without naming them. My code assumed plugin responses looked one way and real plugins disagreed: <code>cniVersion<\/code> is camelCase, real plugins leave out empty optional fields, and the stdin payload needed its field names translated as well. Deleting a network also had to be refused while containers were still attached (Oct 5).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Other fixes from those two weeks, quoted or paraphrased from the commit messages:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Webhook signatures used Rust&#8217;s <code>DefaultHasher<\/code>, which is not a MAC. Now HMAC-SHA256 (Oct 11). TOTP and backup codes were compared with a plain <code>==<\/code>. Now constant time (Oct 11). NAS password checking looked up the user in <code>\/etc\/shadow<\/code> and then returned success without comparing anything. &#8220;Any password, including an empty one, authenticated successfully for any local user.&#8221; That sat under SMB, NFS, FTP and WebDAV auth (Oct 11). Newlines and NULs could be injected into the Kerberos admin scripts and the generated <code>smb.conf<\/code> (Oct 13). Audit logs believed a client-supplied <code>X-Forwarded-For<\/code> (Oct 3). A non-ASCII <code>Origin<\/code> header panicked the CORS layer (Oct 12). NetworkPolicy enforced ports and ignored peer selectors and IP blocks (Oct 9).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The commit messages don&#8217;t say which of these a test caught and which got spotted by reading, so I won&#8217;t claim the tests found them. On the 14th the audit job did flag four new RUSTSEC advisories against rustls, and that was a version bump.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Smaller embarrassments<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;Docker image was building frozen v0.1.0, not HEAD&#8221; (Oct 8). Trunk never built <code>main.css<\/code>, which means the nav dropdowns had no styling at all (Oct 9). The UI hardcoded <code>http:\/\/localhost:8006<\/code> for API and WebSocket calls, fine if you browse from the server itself and nowhere else (Oct 12 and 15). A VM CPU metric wasn&#8217;t divided by vCPU count. Poisoned locks would panic the process (Oct 15).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What I took from it<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The NAS bypass shipped inside a feature I&#8217;d already called complete.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">State on October 15: 53 passing runs against 43 failing on the main workflow and about half the nightlies red. Part 5 is the audit I started on the 16th.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Design decisions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Not much is written down for this fortnight. The one clear call is that deleting a CNI network is refused while containers are attached to it (Oct 5).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Other parts: <a href=\"https:\/\/blog.canutethegreat.com\/index.php\/2025\/10\/13\/horcrux-dev-log-1-the-first-week-lots-of-code-and-no-tests-that-ran\/\">Part 1<\/a>, <a href=\"https:\/\/blog.canutethegreat.com\/index.php\/2025\/12\/31\/horcrux-dev-log-2-my-own-forgejo-a-gentoo-iso-builder-and-an-iso-that-never-quite-booted\/\">Part 2<\/a>, <a href=\"https:\/\/blog.canutethegreat.com\/index.php\/2026\/09\/30\/horcrux-dev-log-3-back-after-nine-months-92-failed-ci-runs\/\">Part 3<\/a>, <a href=\"https:\/\/blog.canutethegreat.com\/index.php\/2026\/10\/21\/horcrux-dev-log-5-auditing-my-own-project-and-what-turned-out-to-be-fake\/\">Part 5<\/a>, <a href=\"https:\/\/blog.canutethegreat.com\/index.php\/2026\/11\/06\/horcrux-dev-log-6-clustering-an-iso-you-can-install-from-and-real-laptops\/\">Part 6<\/a>. The series continues with <a href=\"https:\/\/blog.canutethegreat.com\/index.php\/2026\/11\/07\/horcrux-dev-log-ha-live-migration-three-old-laptops\/\">the latest Horcrux dev log post<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>October 1 to 15, 2026: nightly VM and container tests, a stress suite, and security fixes, including a NAS login that accepted any password.<\/p>\n","protected":false},"author":1,"featured_media":610,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,26],"tags":[369,368,361,291,367],"class_list":["post-586","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security","category-software-engineering","tag-authentication","tag-cni","tag-horcrux-dev-log","tag-rust","tag-testing"],"_links":{"self":[{"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/posts\/586","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/comments?post=586"}],"version-history":[{"count":3,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/posts\/586\/revisions"}],"predecessor-version":[{"id":633,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/posts\/586\/revisions\/633"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/media\/610"}],"wp:attachment":[{"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/media?parent=586"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/categories?post=586"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.canutethegreat.com\/index.php\/wp-json\/wp\/v2\/tags?post=586"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}