Changes for version 0.19 - 2026-08-18

  • SECURITY: a session had no server-side lifetime. `expires` set only the cookie's Max-Age, which is a request to a client that is free to ignore it - the signature carried no time at all, so a cookie captured once (a shared machine, a log, a backup, a proxy) stayed valid for as long as the secret did, and session_expire only asked the browser to forget a value that still authenticated. The expiry is now stamped inside the signed payload
  • New $c->safe_path($path, $fallback?): returns the path when it is same-origin and relative, otherwise the fallback. Punk had no such guard while auth_guard hands every application a ?to= to redirect to, which made the obvious login form an open redirect. Same rules as Punk::OAuth2's same_origin_path, for the same reasons (CVE-2026-75628)
  • The static traversal guard splits segments on a backslash as well as a slash. On POSIX "..\.." is one ordinary filename and traverses nothing, but Windows reads it as a separator, so a guard that split on "/" alone saw one harmless segment where the OS would see two levels up.
  • New hook phase `before_request`, which runs BEFORE routing:
    • hook before_request => sub { my ($c) = @_; $c->stash->{t0} = Time::HiRes::time(); return; };
    • The earliest phase until now was before_dispatch, which runs only after the router has matched - so nothing could observe a request from its start, and nothing ran at all for a 404, a 405, or anything answered by a PSGI or static mount. before_request runs for all of those.
  • The logger takes a record: a lone unblessed hashref is a set of fields, and its `message` key is the message.
    • $c->log->info({ message => 'listing books', books => 12, user => $id });

Documentation

the Punk command line

Modules

a MVC web framework
the per-application registry and boot compiler
the authentication battery
password hashing
cross-origin resource sharing
single-use CSRF tokens
the punk command line: registry, dispatcher and commands
YAML configuration with secrets kept out of the file
the per-request object
base class for Punk controllers
the development error page
an async result that runs on the loop, or blocks
scaffold a new Punk application
security response headers
a level-based logger
the storage-agnostic model tier
the default DBI backend for Punk models
a non-blocking backend for Punk models
a directory of markdown as a documentation site
the api mount: spec-first operations
base class for Punk plugins
rate limiting and IP blocking over Hyperman's shared arena
a lazy wrapper over the PSGI environment
a response builder
the compiled-at-boot route tables (XS)
the handle an under returns
a Server-Sent Events stream
the bounded body of a ranged send_file response
signed cookie sessions
serving files from a directory
an in-process test client for Punk applications
a pure-Perl RFC 6455 codec for testing WebSocket servers
the client side of one WebSocket connection
the outbound HTTP agent on the context
an uploaded file from a multipart form
collecting request validation
the Template::Stencil view engine
the pluggable view engine registry (XS)
a WebSocket connection
pub/sub groups of WebSocket connections

Provides

in bench/apps/cat-lib/BenchCat.pm
in bench/apps/cat-lib/BenchCat/Controller/Root.pm