Daily SEO Note — October 26, 2026: A Cloudflare WAF Rule Can Break Next.js Images
Part of Daily SEO Notes, a daily series.

SEO for Content Writers
The only editorially relevant change Google confirmed in the last 72 hours is a documentation clarification about word separators in URLs. The Search Central Blog has published nothing since October 6, and the Search Status Dashboard logs no ranking, indexing, or serving event anywhere in October — the last confirmed ranking event was the September 2026 spam update, which finished rolling out on October 8. The two things editors are actually talking about this weekend are both unconfirmed, and are labelled as such below.
1. Google restated hyphens over underscores in URLs — a slug rule, not a migration order
On October 23, Google's documentation changelog recorded an update to the URL structure best practices clarifying when to use hyphens rather than underscores to separate words in a URL. This is a documentation clarification, already live; it is not a ranking change and Google did not announce it on the blog.
The URL structure page now says plainly that Google recommends hyphens instead of underscores because “hyphens clearly signal a word boundary,” while underscores are discouraged “for historical reasons” and are commonly used in programming to join names that belong together. It affects all content, but only at one moment: when a slug is first created.
What to do differently in the next article: write the target slug into the brief yourself rather than letting the CMS auto-generate it from a headline that may contain em dashes, ampersands, or colons. Lowercase, ASCII, hyphen-separated, derived from the working headline, with stop words trimmed.
What to stop doing: stop logging existing underscore URLs as defects. Nothing in this clarification asks anyone to migrate a live URL, and a redirect carries real cost that this guidance does not justify. Apply it forward, to new slugs only.
2. AI Overview citation cards are reportedly showing generated summaries, not your copy (unconfirmed)
On October 23, Brodie Clark reported that citation cards attached to Google AI Overviews can now display an AI-generated summary of the cited page, rather than text drawn from the page itself. Barry Schwartz reproduced it on some test queries but not all. Google has not announced this and has not confirmed whether it is a test or a rollout, so treat it as unconfirmed.
If it holds, the editorial consequence is specific: the sentence a reader sees under your citation is composed around their query and does not appear verbatim on your page. That removes the meta description as the lever writers normally reach for. What remains controllable is whether the page contains a clean, self-contained answer that a model can summarise without distorting it — a definition that stands alone in one paragraph, a comparison stated in full sentences rather than implied by a table, a number given with its unit and date.
Because this is unconfirmed, it is deliberately excluded from the brief checklist below. Do not restructure a content programme around a single weekend's observations.
3. Saturday's ranking volatility is a tracker story, not a Google story (unconfirmed)
Roughly fifteen third-party rank trackers spiked on October 24, and Search Engine Roundtable wrote it up on October 25 as a suspected ranking adjustment released Friday into Saturday. That inference is the author's; no Google statement accompanies it, and the same report notes the tracking tools have been behaving erratically for about a month.
The primary evidence points the other way. The Search Status Dashboard — which is where core and spam updates are logged, frequently with no companion blog post — carries no October entry at all. The last ranking incident on it began on September 24 and completed on October 8.
The editorial consequence is to do nothing. A tracker spike with no dashboard entry is not a reason to commission rewrites, pull a publishing slot, or revisit a cluster strategy. Gate that kind of work on a logged event, not on chatter.
Apply to your next brief
- Specify the slug in the brief: lowercase, ASCII, hyphen-separated, derived from the working headline — do not leave it to CMS auto-generation.
- Drop any open ticket that proposes changing an existing underscore URL to hyphens; the guidance is forward-looking and the redirect cost is not justified.
- Gate update and rewrite priorities on a logged entry in the Search Status Dashboard, which currently shows no October ranking event, rather than on third-party volatility charts.
- Keep writing one self-contained, quotable answer paragraph per article — a definition, a direct comparison, or a dated figure with its unit — as standing practice, independent of this week's AI Overview reports.
SEO for Developers
Cloudflare shipped an emergency WAF release on October 25 that adds a Managed Ruleset rule matching every request to the Next.js /_next/image endpoint. It ships with its action set to Log, but Cloudflare warns that any ruleset-level override applying Block will start blocking matching requests the moment the rules deploy. If that describes your account, your entire image pipeline goes dark without a deploy of your own. That is today's one same-day pull request.
1. Cloudflare's emergency WAF rules match /_next/image and Brotli request bodies
Rollout identifier: WAF Release 2026-10-25, Emergency, Cloudflare Managed Ruleset. Two new detections were added for CVE-2026-111497: “Brotli - Request Content-Encoding” (rule ID ending ca706f3c), which matches any request declaring Brotli request-body encoding, and “Next.js - Image Optimizer Path” (rule ID ending 402fe5bb), which matches requests to the image optimizer endpoint. Cloudflare states explicitly that both match legitimate traffic as well as hostile traffic.
Breaking or non-breaking: non-breaking at the default action of Log, and breaking for any zone carrying a ruleset-level override that forces Block. The symptom if ignored is that /_next/image starts returning a Cloudflare block response, so every next/image URL on the site fails at once. Practically that means the LCP element vanishes on image-led templates, CrUX will absorb the regression over its trailing 28-day window, and Google Images and Discover lose the asset entirely while the block persists.
The setting to change is in your WAF managed ruleset configuration, not in the application: review existing ruleset-level overrides, and add rule-specific overrides pinning both rule IDs to Log so a blanket Block override cannot reach them. Then verify from outside your own network — a CDN silently overriding intent is invisible from inside it.
#!/usr/bin/env bash
# Assert the Next.js image optimizer still answers 200 from the public edge.
# Run from CI and from a network outside your own egress IP.
set -euo pipefail
ORIGIN="https://example.com"
SRC="/images/hero.jpg" # a real, in-repo image path
URL="${ORIGIN}/_next/image?url=$(printf '%s' "$SRC" | jq -sRr @uri)&w=1200&q=75"
code=$(curl -s -o /dev/null -w '%{http_code}' -L --max-time 15 "$URL")
echo "GET /_next/image -> ${code}"
if [ "$code" != "200" ]; then
echo "FAIL: image optimizer is not returning 200." >&2
echo "Check WAF ruleset-level overrides for rule id *402fe5bb (Log, not Block)." >&2
exit 1
fi2. The real fix is a Node.js upgrade — the WAF rule is only a shield
Version and date: Node.js shipped v22.23.4, v24.22.1 and v26.12.1 in its October 2026 security releases on October 21. This item sits in today's window because the October 25 Cloudflare release is the mitigation layer for it, and treating that mitigation as the fix leaves the vulnerability in place.
CVE-2026-111497 is rated High. The bundled Brotli decoder reported an invalid block switch as a temporary “need more input” condition instead of a permanent format error, so the streaming decoder kept appending input bytes to an eight-byte internal buffer and wrote past its end. Any application that decompresses attacker-supplied Brotli data through node:zlib can be driven to a crash, process-memory disclosure, or remote code execution. The 26.x, 24.x and 22.x lines are all affected.
Breaking or non-breaking: non-breaking, these are patch releases. The symptom if ignored is not an SEO symptom at all — it is a remotely exploitable image-optimization path on self-hosted Next.js, which is precisely the surface Cloudflare's new rule is watching. Note separately that Next.js already patched its own critical image-optimizer RCE in v16.4.1 and v15.5.28 on October 14; that is a different issue and patching one does not cover the other. The files to change are your runtime pins.
# .nvmrc -- pin the patched runtime
22.23.4
# Dockerfile -- pin the digest-stable patched image
# FROM node:22.23.4-bookworm-slim
# package.json -- fail installs on an unpatched runtime
# "engines": { "node": ">=22.23.4 <23 || >=24.22.1 <25 || >=26.12.1" }
# Verify what is actually running in the deployed container,
# not what the lockfile claims:
node -p "process.versions.node"
node -p "process.versions.brotli ?? 'brotli version not exposed'"
# Fixed lines: 22.23.4 | 24.22.1 | 26.12.13. URL word separators: fix the slug generator, not the existing routes
Date and status: October 23, recorded in the Google Search documentation changelog as a clarification to URL structure best practices; live, non-breaking, no rollout phase. The guidance itself recommends hyphens as word separators and discourages underscores.
The symptom if ignored is mild and indirect — underscore-joined words are read as a single token, which costs you nothing dramatic but gives up a free word boundary. The thing worth engineering attention is the generator, because an auto-slugger that strips punctuation without replacing it is the usual way underscores and run-together words enter a URL set in the first place. The file to change is wherever you slugify titles.
Do not pair this with a redirect migration. Rewriting live URLs to satisfy a documentation clarification trades a certain cost — redirect chains, lost link equity during recrawl, sitemap churn — for an unquantified gain. Change the generator; leave the history alone.
// Normalises a headline into a hyphen-separated, ASCII, lowercase slug.
// Key detail: punctuation becomes a separator, never a deletion, so
// "SEO: on-page/off-page" -> "seo-on-page-off-page", not "seoonpageoffpage".
export function slugify(input: string, maxLength = 96): string {
return input
.normalize("NFKD") // split accents off their base letters
.replace(/\p{M}/gu, "") // drop the combining marks: café -> cafe
.toLowerCase()
.replace(/[\p{Pi}\p{Pf}']/gu, "") // elide quotes, do not hyphenate them
.replace(/[^a-z0-9]+/g, "-") // every other run becomes exactly ONE hyphen
.replace(/^-+|-+$/g, "") // no leading or trailing hyphen
.slice(0, maxLength)
.replace(/-+$/, ""); // the slice may leave a dangling hyphen
}
// slugify("Daily SEO Note — October 26, 2026: Cloudflare's WAF Rule")
// -> "daily-seo-note-october-26-2026-cloudflares-waf-rule"4. Re-verify the AI crawler roster against what your CDN actually enforces
Status: current state, not a dated change. OpenAI publishes no changelog for its crawler documentation, so this is listed as a verification task rather than an announcement — but it is the natural companion to auditing WAF overrides today, since the failure mode is identical: the CDN quietly enforcing something other than what robots.txt says.
OpenAI's bots documentation currently lists four separate agents, and they are four separate decisions: OAI-SearchBot for ChatGPT search surfacing, GPTBot for foundation-model training, ChatGPT-User for user-triggered fetches (which OpenAI notes robots.txt rules may not apply to), and OAI-AdsBot for validating ChatGPT ad landing pages. Most robots.txt files written before this autumn name only the first three. Perplexity documents two — PerplexityBot for search surfacing and Perplexity-User, which it states generally ignores robots.txt because a person requested the fetch.
The symptom if ignored is an unintended policy rather than an error page: an agent you never considered inherits your default-allow, or your WAF returns 403 to a crawler your robots.txt welcomes, and nothing in Search Console will tell you. The file to change is public/robots.txt; the thing to verify afterwards is your edge bot rules, by fetching the policy and watching the logs rather than by reading the config.
# Search surfacing: allow (these decide AI-answer citation eligibility)
User-agent: OAI-SearchBot
Allow: /
User-agent: PerplexityBot
Allow: /
# Model training: a separate decision from search surfacing
User-agent: GPTBot
Disallow: /
User-agent: ClaudeBot
Disallow: /
User-agent: Google-Extended
Disallow: /
# Ad landing-page validation: required only if you run ChatGPT ads
User-agent: OAI-AdsBot
Allow: /
# Note: ChatGPT-User and Perplexity-User are user-triggered fetchers.
# Both vendors document that robots.txt may not govern them, so enforce
# at the edge if you need them stopped -- not here.
Sitemap: https://example.com/sitemap.xmlShip today
- Audit Cloudflare ruleset-level overrides for the two new CVE-2026-111497 rules and pin rule *402fe5bb and *ca706f3c to Log with rule-specific overrides before the managed ruleset reaches your zone.
- Probe /_next/image from outside your own network and assert 200 on a representative image URL; wire the check into CI so a later override change fails a build rather than a crawl.
- Upgrade Node.js to 22.23.4, 24.22.1 or 26.12.1 and pin it in .nvmrc, the Dockerfile and the engines field — the WAF rule is a shield, not the patch.
- Fix the slug generator so punctuation becomes a hyphen rather than being deleted, and explicitly do not open a redirect migration for existing underscore URLs.
- Diff public/robots.txt against the four crawlers OpenAI currently documents, then confirm at the edge that your bot rules are not enforcing the opposite of that file.
Comments
Share your thoughts and join the conversation



