This release brings relative partial references, slug support for branch pages, and a handful of security hardening fixes.
Relative partial references. A partial name starting with ./ or ../ is now resolved relative to the directory of the calling partial. This makes it much easier to write self-contained, movable partial trees, e.g. {{ partial "./item.html" . }} from within layouts/_partials/card/list.html. Relative paths are only allowed from within partials, and paths resolving outside the partials directory is an error. See #15373 and the documentation.
Slugs for section, taxonomy and term pages. The slug front matter now works for branch pages, not just regular pages, and it cascades to descendants. This is particularly useful in multilingual sites, where e.g. content/help/_index.es.md with slug: ayuda gives /es/ayuda/, /es/ayuda/avanzado/ etc. See #14352.
Other notable improvements include the new build.cleanDestinationDir config with keepFiles/keepDirs Glob patterns (#14937, docs), hugo now builds without a config file (#15393), exact numeric comparisons in eq, where, in and the set functions (#15322, #15358), and automatic summaries that no longer end inside an open list or blockquote (#14044).
Security
This release contains several hardening fixes. None of them are known to be exploited, but if you build sites with untrusted themes or modules, you should upgrade.
- Sass imports not found in Hugo's file systems were resolved by the Sass compiler itself, which follows symlinks and knows nothing about the project root. A theme could import a file outside the project and get its content into the published CSS. These imports are now resolved by Hugo and checked against the same
security.allowReadroots as the Node.js tools andjs.Build. 41040cc (thanks to @Hama1cco) - Likewise, imports not found in
/assetswere resolved and read by ESBuild itself. The resolved path is now checked against the allowed read paths before ESBuild loads it. 2aa51f3 (thanks to @Hama1cco) - A symlinked directory in a theme at the parent of a nested mount could expose files outside the module. 2fe9bab
- Explicit heading IDs (e.g.
## Foo {id="..."}) were written unescaped into the table of contentshref, allowing attribute breakout. 671fbf2
Note
- The default
baseURLis nowhttps://example.org/(it was empty). Hugo has always required a valid URL to work properly, so this mostly affects new and test sites, but if you relied on the empty default for relative URLs, setbaseURLexplicitly. bc68654 @bep #14625 #15384 - The root
cleanDestinationDirconfig key is deprecated in favour ofbuild.cleanDestinationDir.enable. The--cleanDestinationDirflag maps to the new key. Note that.gitfiles in the publish dir are now kept by default. 9086193 @bep #14937 eqnow compares numeric values the same way aslt,leetc., so e.g.eq 1 1.0is nowtrue. Also,in,intersect,union,uniq,symdiff,complementandwhere'sin/not innow compare numbers exactly rather than viafloat64, and no longer require the Go types to match. 4d628bb 366377b @bep #15322 #15358- A user table render hook is now preferred over the embedded one. 140d936 @jmooring #15389
- Automatic summaries are expanded past
summaryLengthwhen needed so they don't end inside an open container element. This may change the summary for some pages. d692a24 @bep #14044
Bug fixes
- hugolib: Fix failing integration test fdbba5a @jmooring
- Fix build with Go 1.26 on Fedora 44 Beta 2782bfd @flyn-org
- Fix smartcrop with rotation (#15371) 5edd05b @bep #11266 #15369
- ci: Fix broken magefile 1d87ee5 @bep
- tpl/collections: Fix union of slices with different numeric element types ffbcdba @hktitof #15323
- Fix stale page content when several files in the same dir change in one batch a374b86 @bep #15330
Improvements
- Update .gitignore f6606f1 @bep
- tocss: Confine Sass import fallbacks to the allowed read paths 41040cc @bep
- js: Confine ESBuild's fallback resolver to the allowed read paths 2aa51f3 @bep
- commands: Allow building without a config file c7f9999 @bep #15393
- collections: Preserve slice type when appending an empty slice dd16df1 @jakezwang #11131
- tpl/tplimpl: Prefer user table render hook over embedded 140d936 @jmooring #15389
- Avoid allocating in SitesMatrix.MatchSiteVector 83ab799 @bep
- Add slug support for section, taxonomy and term pages 5d43ab7 @bep #14352
- tpl: Avoid reflect.Value.Call for common signatures 806a62e @bep #15385
- ci: Disable vet when running tests 8bac4de @bep
- tpl/partials: Support relative partial paths from within partials (#15376) bd1588b @bep #15373
- config: Add build.cleanDestinationDir config 9086193 @bep #14937
- commands: Make testscripts/commands/hugo__clean_destination_dir.txt portable a74b753 @bep #8433
- commands: Handle missing staticDir in cleanDestinationDir 07b9fba @jmooring #8433
- hugofs: Cache symlink checks 09fa49b @bep
- hugofs: Drop symlinks in virtual ancestor dirs of nested mounts 2fe9bab @bep
- markup/tableofcontents: Escape heading IDs in ToC HTML 671fbf2 @bep
- hugofs: Allow symlinked mount roots in the main project 25f2856 @bep #15367
- Expand and consolidate BOM trimming cb6a707 @bep #15355 #15361
- tpl/collections: Compare numbers exactly in set operations and where 366377b @bep #15358 #15359
- ci: Skip vet on Windows 10bb97b @bep
- Revert "parser/metadecoders: Strip BOM from data prior to unmarshalling" 51cd9e6 @bep
- parser/metadecoders: Strip BOM from data prior to unmarshalling ec578f0 @jmooring #15355
- tpl: Reformat templates with new formatter version 5698de9 @bep
- resources/page: Balance container tags in automatic summaries d692a24 @bep #14044 #14927
- config/security: Add an integration test 3be817e @bep
- tpl/compare: Consolidate numeric comparisions 4d628bb @bep #15322 #15347
- tpl/strings: Add a strings.FirstLower function aaacd12 @jmooring #15332
- Update brevity guideline in AGENTS.md 881c0ec @bep
Dependency Updates
- build(deps): bump github.com/olekukonko/tablewriter from 1.1.4 to 1.1.5 1567bde @dependabot[bot]
- build(deps): bump github.com/dustin/go-humanize from 1.0.1 to 1.1.0 9e4059c @dependabot[bot]
- build(deps): bump golang.org/x/tools from 0.49.0 to 0.50.0 8e3bbe6 @dependabot[bot]
- build(deps): bump golang.org/x/image from 0.45.0 to 0.46.0 753c5fc @dependabot[bot]
- build(deps): bump golang.org/x/text from 0.41.0 to 0.42.0 facde8a @dependabot[bot]
- build(deps): bump go.opentelemetry.io/otel/sdk from 1.44.0 to 1.45.0 c7e1a8e @dependabot[bot]
- deps: Bump github.com/bep/imagemeta from 1.0.0 to 1.0.1 (#15338) ec57bb7 @dependabot[bot] #15324