Skip to content

Oink 0.7.1 — Nothing leaves the page, and bad input stops breaking builds

Oink 0.7.1 is a security and validation patch. Swagger UI stops sending your spec URL to a third party, misconfigured values warn instead of killing an ordinary build, and the OpenAPI and terminal components finally behave in print, Markdown and RSS the way every other component already did.

Oink 0.7.1 changes no component API and needs no content edits. It closes the code findings from an external review of the 0.7.0 line: one real privacy leak, a class of configuration values that could stop a build outright, and three components that had never been taught what a non-HTML output is.

At a glance

  • Swagger UI no longer contacts the online validator. A published API page made a third-party request on every view; it no longer makes any.
  • A URL written into site configuration now passes the same safety check as one written by an author.
  • A mistyped number or boolean in params warns and falls back instead of ending an ordinary hugo server session.
  • swagger, redoc and asciinema emit a plain link in print, Markdown and RSS, and load their runtime only in interactive HTML.

Swagger stopped phoning home

Swagger UI ships with an online validator enabled by default, pointed at validator.swagger.io. It skips that request for localhost, which is why no local preview and no browser test ever showed it — and why every deployed API page was quietly handing your spec URL to a third party. On an intranet that URL is an internal hostname.

The initializer now pins validatorUrl: null, and it moved out of an inline <script> into a cacheable js/chunks/swagger-init.js. A normal build still downloads nothing, and now a normal view uploads nothing.

Configured URLs go through the same gate as authored ones

Two settings reached an href unchecked: the custom links in params.ui.page_context_menu.links and the archived-site banner’s params.url_latest_version. A javascript: URL in either one rendered as a working, clickable script.

Both now run through the theme’s shared URL policy: an unsupported scheme warns and the link is dropped rather than repaired. The archived-version banner additionally escapes its URL where it is written into the page, because clearing the scheme is not the same as being safe inside an HTML attribute.

Custom links also skip entries with a missing or non-text name, and the separator above them only appears when a link actually survives.

Bad configuration warns; it no longer kills the preview

The theme’s rule has always been that invalid author or config input warns, falls back to a documented default, and keeps hugo server usable — with --panicOnWarning turning that warning into a failure where you publish. A group of numeric and boolean keys had never been wired into it.

Before 0.7.1, a value like blog_index_size: nope ended the build with a Go template error. Others were worse for being quiet: sidebar_width_min: -50 emitted a negative pixel width without a word, and blog_index_columns: 2.5 fed a fraction into a CSS grid.

Every numeric and boolean key now resolves through the shared validator:

Input Before Now
blog_index_size: nope build fails warns, uses 12
blog_index_size: 0 silently becomes 12 warns, uses 12
sidebar_width_min: -50 emits -50px warns, uses 220
sidebar_width_min: 300 with max: 200 inverted layout warns, uses 220/480
blog_index_columns: 2.5 fraction into CSS warns, uses 3
sidebar_item_overflow: clip silently ellipsis warns, uses ellipsis
print.toc: nope silently true warns, uses true

The same treatment reaches the Landing sections: the hero’s media.ratio and media.max_width, the capabilities board’s columns and rules, and a marquee’s rows. The hero’s two style inputs were the notable ones — they were written straight into a style attribute, so a page’s own front matter could put arbitrary CSS on the page. ratio now takes exactly two track sizes ('1fr 240px'), max_width a plain CSS length.

If you have been running with a value the theme silently corrected, you will see a new warning. That is the point — build once with --panicOnWarning after upgrading to find them.

OpenAPI and terminal recordings respect the other outputs

Every Oink component renders once and then adapts to the output it lands in: interactive HTML, static print, plain Markdown for agents, and RSS. Sixteen components already did this. swagger, redoc and asciinema did not — they rendered their interactive markup into all four.

The result was a Markdown output carrying <div class="td-asciinema"> and a JSON config block, a printed page holding an empty container where a player should be, and a single-page print that actually downloaded the player runtime to show one frozen frame.

All three now read the output format:

Output What you get
HTML the full interactive component
Print a labelled static link showing the URL
Markdown / LLMS a plain Markdown link, nothing else
RSS the same plain link

Only interactive HTML registers the runtime, so print and machine outputs load no player, no Swagger bundle and no ReDoc bundle. A cast or spec URL now also goes through the shared URL policy, and a mistyped speed, cols, rows or marker time warns and is ignored instead of ending the build.

Smaller repairs

  • The capabilities board’s rule bars render at their authored widths. The template had always emitted them; the stylesheet never read them.
  • The generated configuration schemas match what Hugo actually parses. Trailing comments in hugo.yaml were leaking into eleven default values — print.toc shipped as the string "true # section print views…" — and four comment blocks documented the wrong key. Keys that exist only to warn about a rename no longer appear in editor completion.
  • A hero whose media is not a map warns and drops the media instead of ending the build.

Upgrading

hugo mod get github.com/pgsty/[email protected]
hugo mod tidy

No content, configuration or template changes are required. One thing to do after upgrading: run a build with --panicOnWarning once. Configuration that used to be corrected silently now says so, and that build is where you will see it.

The complete list is in CHANGELOG.md.