From 01672cf6eecafeea41d28c34a4662501352ddc89 Mon Sep 17 00:00:00 2001 From: hoelee Date: Sun, 20 Sep 2026 09:53:01 +0800 Subject: [PATCH] Draft: the > character that broke authentik brand CSS (EN+ZH) Held unpublished (draft: true). Records the u003e escaping bug: authentik renders > in branding_custom_css as the literal text u003e, so any child combinator produces an invalid selector that silently matches nothing. Includes the cssRules-based debugging order and the character safety probe. Docs: not yet recorded in project-state.md --- .../posts/authentik-css-greater-than-bug.md | 270 ++++++++++++++++++ .../zh/authentik-css-greater-than-bug.md | 253 ++++++++++++++++ 2 files changed, 523 insertions(+) create mode 100644 src/content/posts/authentik-css-greater-than-bug.md create mode 100644 src/content/posts/zh/authentik-css-greater-than-bug.md diff --git a/src/content/posts/authentik-css-greater-than-bug.md b/src/content/posts/authentik-css-greater-than-bug.md new file mode 100644 index 0000000..f700094 --- /dev/null +++ b/src/content/posts/authentik-css-greater-than-bug.md @@ -0,0 +1,270 @@ +--- +title: "The Character That Silently Broke My authentik CSS" +description: "My authentik custom CSS looked correct, matched the right elements, and did nothing. The cause was a single > character that authentik escapes into invalid text." +pubDate: 2026-09-20 +category: devops +tags: ["authentik", "css", "self-hosting", "debugging", "browser"] +ogImage: /og/authentik-css-greater-than-bug.png +banner: /banners/authentik-css-greater-than-bug.png +draft: true +--- + +I spent an afternoon on a CSS rule that should have taken thirty seconds. + +I wanted to hide one line in the authentik login page footer — the +hardcoded "Powered by authentik" credit. The rule I wrote has worked in +every other project I've touched: + +```css +ul.pf-c-list > li:last-child { + display: none !important; +} +``` + +It did nothing. Not "it looked slightly off" — the element stayed +fully visible. What follows is the four wrong answers I chased, the one +correct answer, and the debugging move I should have made first. + +## Why this matters beyond one footer line + +If you self-host authentik and have ever pasted CSS into +**System → Brands → Custom CSS** and seen zero effect, you have probably +concluded you did something wrong. You almost certainly didn't. The +stylesheet is accepted, stored, served to the browser, and parsed — and +then silently fails, with no error in any log you can reach. + +That is the worst kind of bug: no feedback loop. This post gives you the +loop back. + +## Wrong answer #1: it's shadow DOM, so CSS can't reach it + +My first assumption. Modern web components often hide their markup +behind a shadow root, and normal document CSS cannot cross that +boundary. The authentik login page is rendered by web components — I had +seen `` and `` in the page source — so this +felt obviously right. + +I read the component definition out of the shipped bundle to confirm: + +```js +var oe = class extends L { + createRenderRoot() { return this } + render() { ... } +} +``` + +`createRenderRoot(){ return this }` means **no shadow root** — the +component renders into the light DOM. Ordinary CSS reaches it just fine. + +Wrong answer. Moving on. + +## Wrong answer #2: the CSS isn't being injected at all + +Next theory: my CSS never made it into the page. I grepped the served +HTML for a distinctive class from my rule: + +``` +