# Hugo 0.165.0-0.166.0 upgrade guide

> Hugo 0.166.0's security hardening, and a few smaller changes, can break a Docsy site's build or silently change its output. Find the ones that apply to your site, each with its fix.

---

Site [llms.txt](/fr/llms.txt)

---

This post is a companion to the [Docsy 0.18.0 release post](0.18.0/), which
names the [Hugo version that 0.18.0 supports](0.18.0/#hugo).

## Upgrade summary

- **This guide is for you if** you're:
  - [Upgrading to Docsy 0.18.0](0.18.0/#upgrade)
  - Upgrading only Hugo, past 0.164.x
- Review <span class="badge text-bg-warning rounded-pill text-small">BREAKING</span> changes:
  <a id="breaking-changes"></a>
  - <i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> [Security hardening](#security): Node tools,
    symlinked mounts, remote fetches, Org content
  - <i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> [Glob patterns rewritten](#globs)
  - <i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> [KaTeX stylesheet floor](#katex)
  - <i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> [URL and template changes](#urls-templates)
  - <i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> [Tailwind allow-list (0.165.0)](#tailwind)
- Review **deprecations**: [Imaging config](#imaging)
- Where a step sets a [`security`][hugo-security] list, write the whole list:
  Hugo replaces a configured list rather than merging it with the default.
- <i class="fa-solid fa-rocket text-primary px-1"></i> Jump to
  [Upgrade to Hugo 0.166.0](#upgrade) once you're
  ready.

## <i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> Security hardening (0.166.0) {#security}

Hugo 0.166.0 is mostly a hardening release: it drops symlinked mounts, confines
Node tools to allowed roots, checks the addresses that remote fetches resolve
to, and denies Org mode content by default. Each item can stop a site's build or
silently drop its files. For the details, see Hugo's [0.166.0][hugo-0.166.0]
release notes.

### Actions {#security-actions}

<i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> **Applies if** your project has a symlink that resolves
outside it, under `node_modules` for example. Hugo 0.166.0 fails PostCSS and
other Node tools before running them when a symlink escapes the allowed roots.

- Set `security.node.permissions.allowRead` to the whole list with the link's
  target added, `['.', 'TARGET']`, where _`TARGET`_ is the path the link
  resolves to.

<i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> **Applies if** a symlink sits on a mount's path,
wherever it points: a mount root such as `assets/` or a module mount's `source`
(dropped since 0.166.0), a directory inside one such as `assets/vendor/x`
(dropped since 0.165.0), or a relative `source` that passes through a link. A
symlinked theme directory (`themes/docsy -> ../docsy`) still mounts, but counts
as a symlink that resolves outside the project for the Node gate above when
PostCSS runs (Docsy runs it in production with a `postcss.config.*`, and for RTL
languages). Docsy's own mounts read two `node_modules` packages through three
mounts, which pnpm and `npm link` install as symlinks: the Bootstrap and Font
Awesome Sass imports then fail with no pointer to the cause, and the Font
Awesome webfonts vanish from an otherwise green build.

- Replace the link with the real directory (pnpm: `node-linker=hoisted`), or
  mount the link's target by an absolute `source`, for every mount the link
  affects, and re-declare your project's own `assets` and `static` mounts: a
  project mount for a component [replaces Hugo's default mount][default-mounts]
  for it, silently.

<i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> **Applies if** your build runs behind an `HTTP_PROXY` or
`HTTPS_PROXY`. Docsy itself fetches Mermaid, MarkMap, and KaTeX assets at build
time, so a proxied build is affected even if your templates fetch nothing: Hugo
0.166.0 ignores the proxy variables unless told to honor them.

- Set `security.http.proxyFromEnvironment` to `true`.

<i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> **Applies if** your build fetches resources from a
private or internal host. Hugo 0.166.0 rejects loopback, private, link-local,
and CGNAT addresses under the default `security.http.urls` allowlist.

- Set `security.http.urls` to a list naming your hosts and the CDNs Docsy
  fetches from (`cdn.jsdelivr.net`, `unpkg.com`): the address check stands down
  for a customized list.

<i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> **Applies if** your content includes Org mode files
(`.org`). Hugo 0.166.0 denies `text/org` by default, as it passes raw HTML
through.

- Opt back in by setting `security.allowContent` to the whole list without the
  `text/org` denial: `['! ^text/html$']`.

## <i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> Glob patterns rewritten (0.166.0) {#globs}

Hugo 0.166.0 replaced its glob-matching engine. Patterns that relied on the old
engine's bugs match differently; literal paths are unaffected.

- `**/` matches one or more directories; the old engine also let it match none:
  - `**/x` no longer matches a top-level `x`. Add `x` as a second pattern; the
    `{**/,}x` alternation matches nothing before 0.166.0.
  - `a/**/b` no longer matches `a/b`.
- `\` is an escape character.
- Malformed patterns fail the build.

### Actions {#globs-actions}

<i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> **Applies if** your site uses glob patterns:

- In config: module mounts' `includeFiles`, `excludeFiles`, and `files`;
  `cascade` targets; `segments`; `deployment` targets' `include` and `exclude`;
  `noVendor`.
- In templates: `.Resources.Match`, `resources.Match`, and kin.

Then:

- Re-test each pattern against the files it should select.
- For a `!` exclusion, also check the built output for files that should be
  absent: a pattern that stops matching publishes them with no warning.

## <i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> KaTeX stylesheet floor (0.166.0) {#katex}

Hugo 0.166.0's bundled KaTeX, the one behind `transform.ToMath` and Docsy's
`math` fences, emits markup that needs a KaTeX 0.18.4 or
later stylesheet; an older one misrenders some expressions. Docsy 0.18.0's pin,
KaTeX 0.18.9, satisfies it
([dependency versions](0.18.0/#script-dep-pins)).

### Actions {#katex-actions}

<i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> **Applies if** your site renders math and serves a KaTeX
stylesheet below 0.18.4, through `params.katex.version`
or an overridden `scripts/katex.html`.

- Remove your pin to take Docsy's default, KaTeX 0.18.9, or
  update an overridden partial's stylesheet to it; for a custom pin, see [KaTeX
  version][katex-docs].

## Imaging config deprecations now warn (0.166.0) {#imaging}

Hugo 0.163.0 deprecated the global `imaging.quality` and `imaging.compression`
keys for per-format ones ([Hugo 0.158+ guide](hugo-0.158.0+/#imaging)); 0.166.0
raises the notice to a build `WARN`, which fails the update guide's no-warnings
check.

### Actions {#imaging-actions}

<i class="fa-regular fa-wand-magic-sparkles fa-lg text-info px-1"></i> **Applies if** your site config still sets
`imaging.quality` or `imaging.compression`.

- Apply the Hugo 0.158+ guide's
  [Imaging actions](hugo-0.158.0+/#imaging-actions).

## <i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> URL and template changes (0.166.0) {#urls-templates}

Two smaller 0.166.0 changes can move a page or truncate one: a title's `/` no
longer splits a title-derived URL into two segments, and a bare `return` now
works in every template, where it used to be ignored outside partials.

### Actions {#urls-templates-actions}

<i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> **Applies if** your `permalinks` use `:title`, or
`:slug` on pages that set no `slug`, and a title contains a `/`. Hugo 0.166.0
derives one URL segment from the title (`watch-listen-to-this`) where it used to
nest two (`watch/listen-to-this`), so the page's URL moves without a redirect;
filename-based URLs, taxonomy pages, and term pages are unaffected.

- Add an `aliases` entry for the old URL. Under `:slug`, an explicit `slug`
  keeps it; under `:title`, it doesn't.

<i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> **Applies if** your own templates use `return` outside a
partial. Hugo 0.166.0 honors it there: a bare `{{ return }}`, ignored before,
now ends the template's output; `return` with a value fails the build, as it did
before.

- Remove it, or move the logic into a partial.

## <i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> Tailwind allow-list (0.165.0) {#tailwind}

Hugo 0.165.0 is a feature release ([notes][hugo-0.165.0]); besides the symlink
rule above, its change for Docsy sites is that `tailwindcss` left the default
`security.exec.allow` list.

### Actions {#tailwind-actions}

<i class="fa-solid fa-triangle-exclamation fa-lg text-warning px-1"></i> **Applies if** your site runs Tailwind through
`css.TailwindCSS`.

- Set the list with `tailwindcss` added back:

  ```yaml
  security:
    exec:
      allow:
        [
          '^(dart-)?sass$',
          '^go$',
          '^git$',
          '^node$',
          '^postcss$',
          '^tailwindcss$',
        ]
  ```

## <i class="fa-solid fa-rocket text-primary px-1"></i> Upgrade to Hugo 0.166.0 {#upgrade}

After addressing the actions that apply to your site, upgrade to Hugo
[0.166.0][hugo-supported-version] ([Update
Hugo][update-hugo]).

### <i class="fa-solid fa-square-check text-primary px-1"></i> Sanity checks

Confirm that you've addressed [every action][] that applies to your site. Then:

- Upgrading as part of [Docsy 0.18.0](0.18.0/)? Continue with its
  [upgrade section](0.18.0/#upgrade).
- Otherwise, finish with the [generic site checks][check].

<!-- prettier-ignore-start -->
[check]: /docs/update/#check
[default-mounts]: https://gohugo.io/configuration/module/#default-mounts
[every action]: #upgrade-summary
[hugo-0.165.0]: https://github.com/gohugoio/hugo/releases/tag/v0.165.0
[hugo-0.166.0]: https://github.com/gohugoio/hugo/releases/tag/v0.166.0
[hugo-security]: https://gohugo.io/configuration/security/
[hugo-supported-version]: <https://github.com/gohugoio/hugo/releases/tag/v0.166.0>
[katex-docs]: /docs/content/diagrams-and-formulae/#katex-version
[update-hugo]: /docs/update/#update-hugo
<!-- prettier-ignore-end -->
