Security Advisories (1)
CVE-2026-75870 (2026-08-22)

Punk versions before 0.18 for Perl allow session cookie forgery via an empty default HMAC key when a session is declared without a secret. The session keyword freezes its options onto the application as given: it does not require a secret, warn, or refuse to start when one is absent. The cookie read and the write-back both default that key to the empty string, so a declaration with no secret option, or with an undefined or empty one, signs and verifies with a zero-length HMAC-SHA256 key. An attacker who knows the cookie format can then mint one offline carrying any contents the session holds, such as a user identifier or a role. Nothing marks the misconfiguration at runtime: cookies are well formed and sessions round-trip as expected.

NAME

Punk::Router - the compiled-at-boot route tables (XS)

DESCRIPTION

Internal to Punk, and implemented entirely in C (include/punk/punk_route.h). The object is a blessed IV-ref to the C router; every method is an XSUB.

new opens an accumulation phase and add records raw routes. compile resolves each route's target and guards to coderefs - the one step that must stay Perl, since they are Perl code resolved against the app's controller classes - through the $resolve callback, then does all of the router work in C: classify static vs dynamic (a : or * anywhere makes a route dynamic), expand ANY per method, reject duplicate routes and a misplaced *splat, parse dynamic paths into typed segments, and build the exact-match table, the per-path Allow lists, the dynamic records and the per-route record hashrefs.

Matching is one C call: an exact hash lookup for static routes (match_static), a memcmp'd typed-segment walk for dynamic ones with the 405 Allow set computed on a miss (match). :name captures one segment, *name the rest, HEAD falls back to GET, ANY matches every method. Both return a record index; records is the array they index into.

METHODS

new

The router handle (accumulation phase).

add(method => $m, path => $p, target => $t, guards => \@g)

Record one raw, unresolved route. The path must start with /. Chains.

compile($resolve, \@extra?)

Resolve targets and guards through $resolve->($target, $desc) and build the tables in C. $extra is an optional arrayref of the same record shape (the docs UI routes). Returns the handle; ANY static routes expand per method, and a duplicate route or a misplaced *splat croaks.

records

The compiled record hashrefs (code, guards, method, path), indexed by the record index match_static / match return.

match_static($method, $path)

The record index of an exact static hit (HEAD falls back to GET), or the empty list.

match($method, $path)

($index, \%captures) on a dynamic hit; (undef, \@allow) when the path exists under other methods (a 405); the empty list for a 404.

AUTHOR

LNATION <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)