Pi-hole FTL v6.8, Web v6.6.1 and Core v6.5 released

Pi-hole FTL v6.8, Web v6.6.1 and Core v6.5 released

Pi-hole FTL v6.8, Web v6.6.1 and Core v6.5 are now available.

This release fixes a number of security advisories across FTL, Web and Core. Thank you to everyone who reported them: @abdoghazy2015, @KimiSecurityTeam, @keithlinneman, @Pedromdsn, @Jgarcg40, @Rakan78, @dagadjno, @010011110, @ChrisLundquist and @KHr00t.

Before updating, please read the changelogs below. Update with pihole -up. If you want a safety net, take a backup of your configuration first with Teleporter (Settings -> Teleporter in the web interface, or pihole-FTL --teleporter).

The Docker image is tagged 2026.10.0.

Security fixes

High

Medium

  • FTL: local file contents echoed when parsing a file:// adlist (GHSA-667h-gpmh-7gxc, CVSS 6.5): an authenticated user could read files the pihole user can open. Needs the matching Core change (#6706). Reported by @Rakan78.
  • FTL: app sessions could read password hashes and the TOTP secret (GHSA-v53r-4564-3449, CVSS 6.5; duplicate GHSA-846w-3j3v-2hx8): read-only app sessions could read both via /api/config and /api/teleporter. Reported by @Pedromdsn and @010011110; fix by @010011110.
  • FTL: out-of-bounds write in the API TXT buffer (GHSA-8fc6-q9x4-892v, CVSS 5.9): needs a long upstream server list, no authentication. Reported by @dagadjno.
  • FTL: EDNS(0) data leaking between clients’ queries (GHSA-xj4x-gf2g-r6m7, CVSS 4.2): data from one packet could be applied to another client’s query. Reported by @010011110.

Low

  • Core: file:// adlist read check and curl could resolve different files (GHSA-g63w-24cr-p3w6, CVSS 2.2): a bypass of the read check that the FTL file:// fix relies on, needing an admin who can add adlists plus a symlink and decoy on the filesystem. Local lists are now read with cat as the user whose access was checked.
  • FTL: cross-site requests and DNS rebinding against a passwordless install (GHSA-322h-f873-hp54): with no password set, any website opened on the network could reach the API through the visitor’s browser. FTL now refuses cross-site browser requests and unrecognised Host names when no password is set. Reported by @ChrisLundquist.
  • FTL: race when deleting a DHCP lease (GHSA-v8mj-cqgw-63rj, CVSS 2.2): needs an authenticated client and the DHCP server enabled. Reported by @010011110.
  • FTL: crash when searching domains during a list reload (GHSA-9828-2f2q-2c8v, CVSS 2.2): needs a valid session. Reported by @010011110.
  • FTL: crash on a malformed POSTed regex array (GHSA-mqr7-j2p5-5495, CVSS 2.7): needs a valid session. Reported by @010011110.
  • Web: stored XSS on three settings pages (GHSA-rmr4-hqc8-825f, GHSA-3vhj-5284-xrmm, GHSA-qfpp-28mj-pj6p, CVSS 3.5 / 3.1 / 3.1): Settings > All settings, Local DNS Records and DNS. Reported by @KHr00t; fixed by @rdwebdesign.

FTL v6.8

This is a minor release rather than v6.7.2: there are enough visible behaviour changes that a patch version would undersell it. It backports the bug fixes that landed on development since v6.7.1 and updates the embedded dnsmasq (v2.93+30) and SQLite (v3.53.3).

Improvements

  • The live log is now stored as a ring buffer instead of moving the whole buffer for every new line, which costs far less CPU per cached answer.
  • Internationalised domain names on lists are converted to punycode with libidn2 and block, instead of being rejected as invalid.
  • Long-term statistics are grouped before joining the name tables (faster), and two unused in-memory indexes are gone, saving about 22 MB per million queries.

Notable fixes

  • Flushing the logs deleted the whole long-term history, not only the last 24 hours, and moved the graph a day into the future.
  • Crashes with 257+ alias-clients, with a no-longer-forced FTLCONF_ array, and with database.DBinterval = 0.
  • Group and list changes not reaching a client until the next reload, stale forced replies, and missing EDE on the first block.
  • A file path containing + (or any other printable ASCII) was reset to its default on start-up.
  • An open redirect in the .lp compatibility redirect, and / ignoring webserver.serve_all.
  • Pi-hole’s own certificate for a custom webserver.domain was never renewed, and a domain longer than 64 characters ended up as an oversized CN.
  • The empty-DS DNSSEC loop, via dnsmasq, plus its double-free and information disclosure fixes.
  • An API session could enable misc.readOnly through a Teleporter archive, and pihole.toml.lock failed on NFS.
  • Any LAN client could make FTL add a new PTR record for every spelling of its own address until a restart.
  • The CLI password file and pihole-tmp.db were briefly or permanently readable by everyone.
  • On ARM and RISC-V the MAC address of a new device was never looked up at query time, so its MAC-based groups only applied later.
  • Raising misc.privacylevel at runtime did not cover domains and clients already seen, and an ntp.sync.interval above about 24.8 days made the NTP client sync back to back.
  • DNS stalls on list reloads and rate limiting, GC double processing, lost queries at shutdown, and wrong long-term statistics.
  • Old queries were never deleted from pihole-FTL.db on a host that restarts FTL at least once a day.
  • dhcp-discover printed the DNSSL labels of Router Advertisements unescaped.
  • Clients without a MAC address (e.g. a WireGuard peer) stayed in the default group until the next list reload, because the groups of a new client were resolved before its interface was known.
  • The load check counted only the CPUs a container was limited to, while /proc/loadavg shows the host’s load, so the long-term load warning fired spuriously and /api/info/system inflated the load percentage in LXC/Docker with fewer cores. FTL now counts all present host CPUs.
  • Assorted API fixes: CORS headers on 204 and error responses, the reply shape of /api/queries at privacy level 3, /api/history/clients at every privacy level, 64-bit swap figures in /api/info/system, and a rejected POST /api/teleporter upload whose import field does not parse.
  • FTLCONF_files_log_ftl was not used for log lines on early startup.

Behaviour changes to be aware of

  • Invalid values found in pihole.toml are rejected and reset to the default: database.DBinterval of 0, a webserver.tls.cert below the webroot, a non-base32 webserver.api.totp_secret, relative paths for files FTL writes, and a files.tmp_db that names another file Pi-hole keeps (e.g. pihole-FTL.db). A webserver.api.maxHistory above 86400 is reduced to 86400. A list (e.g. dns.hosts) now loses only its invalid entries instead of being reset as a whole.
  • With webserver.serve_all = false, / under a host other than webserver.domain now returns a 404, so a custom index.html in the webroot no longer shows up at http://<ip>/. Behind a proxy that does not strip webserver.paths.prefix, the prefixed path returns a 404 as well.
  • A renewed self-signed certificate comes with a new CA, so an imported tls_ca.crt has to be imported again.
  • FTL no longer hands a symbolic link (e.g. pihole-FTL.db or FTL.log linked to another disk) to the pihole user, and warns about it on every start. Such a target has to be owned by pihole already.
  • When FTL runs as root it only changes ownership or permissions of regular files directly in /etc/pihole and /var/log/pihole, and refuses a symbolic link as log file (including files.log.dnsmasq). Started as pihole, a linked log file keeps working.
  • A blocking timer on an unchanged status now switches to the opposite mode when it expires.
  • The host’s own interfaces show up in the network table, and shutdown may wait up to 30 seconds for a busy database thread.
  • dnsmasq adds the option4: syntax and DHCPv6 vendor classes.
  • Changing ntp.sync.interval restarts FTL, ntp.sync.count = 0 is rejected, and POST /api/action/gravity answers 409 while a run is in progress.
  • Queries older than database.maxDBdays are deleted in the first night after a start, 10000 at a time. A database that kept growing will lose its whole backlog in the first night after the update.
  • A v5 Teleporter import replaces the upstreams, reverse servers and excluded domains/clients instead of adding to them.

Web v6.6.1

A patch release for the stable line while development is mid-rework (AdminLTE 4 / Bootstrap 5).

  • Query Log: show the actual API error (e.g. “The item is already present”) instead of a generic network error.
  • Conditional Forwarding: reject CIDR and otherwise invalid server IPs.
  • Static DHCP leases: fix the tag: validation regex and allow internal underscores in hostnames.
  • hexEncode() now handles code points above U+FFFF.
  • Login no longer blames the password for a refusal that is not about it.
  • Query Log: the API URL is no longer encoded twice.
  • Bundled Moment.js bumped to 2.31.0.
  • DNS settings: clearer “local requests” wording, and an emptyTable typo fixed.

Core v6.5

  • Stop double-rotating logs now that pihole is in /etc/logrotate.d.
  • Remove the deprecated arpflush command in favour of networkflush.
  • Improve gravity error handling.
  • Fix unquoted variable expansion in rm paths.
  • Send USR2 after logrotate.
  • Keep /etc/pihole/versions readable by all users.
  • Remove Debian 11 from the CI distro matrix.
  • Fix URL parsing in gravity.sh.
  • Improve the gravity database schema for performance: WITHOUT ROWID junction tables, new indexes for group lookups and cheaper triggers. Existing databases are migrated to schema version 21 on update.
  • Store the listsCache directory next to gravity.db instead of always in /etc/pihole.
  • Run the update checker and the FTL prestart file fix-ups as the pihole user, and only trust git repositories the pihole user cannot modify.
  • Read local file:// adlists as the user whose access was checked, instead of via curl.
  • Parse local file:// adlist URIs with parameter expansion and path canonicalisation (RFC 8089), by @mwoolweaver.
  • Pass the adlist source URL to FTL’s parseList (needed by the FTL v6.8 file:// adlist fix).
  • Flush the last 24 hours of queries through the FTL API instead of touching the database directly.
  • Stop granting CAP_CHOWN to everything pihole-FTL executes (kept in the ambient set of the FTL service).

New contributor: welcome and thank you to @candygoogy for their first contribution!

Thanks

Thank you to everyone who contributed code, reported issues and tested: @010011110, @DL6ER, @PromoFaux, @yubiuser, @rdwebdesign, @darkexplosiveqwx, @mwoolweaver, @simonkelley, @dschaper, @candygoogy, @10adnan75, @zhouyuefu, @TheKhanj, @pankpan, @ooonea, @luizluca, @davidnich, @niklas-e, @mordyovits and @RMA1313.