Security Advisories (2)
CVE-2026-75628 (2026-08-20)

Punk::OAuth2 versions before 0.03 for Perl allow an attacker-chosen off-site redirect after login because same_origin_path accepts a backslash or tab in the return parameter. oauth2_login reads the return parameter from the initiation request, runs same_origin_path over it, and stores the survivor in the session flow record as the post-login redirect target. That check rejects a value that does not begin with a slash, one with a slash as its second byte, and one containing CR or LF. A backslash and a tab pass. The URL Standard treats a backslash as equivalent to a slash for special schemes, so `/\evil.example` parses with the authority `evil.example`. It also strips ASCII tab before parsing, so a tab between two leading slashes leaves `//evil.example`. A crafted link to the application's own login route lands the victim on the attacker's site after a genuine authentication. The redirect carries no authorization code or access token.

CVE-2026-75866 (2026-08-22)

Punk::OAuth2::Server versions through 0.03 for Perl issue access tokens outside a client's registered scopes and grant types because no authorization path reads them. Punk::OAuth2::Server::Store registers scopes and grant_types per client and documents both as client registration. token dispatches on the grant_type in the request body, so a client registered for authorization_code alone can ask for client_credentials, and that arm passes the requested scope straight to the minter, which signs it into the at+jwt access token. authorize copies the query scope into the authorization code record without comparing it against the registration, leaving the optional consent hook as the only check between an arbitrary scope and the issued code. redirect_uris on the same client row is read and enforced. A registered client can obtain a correctly signed token carrying any scope it names, and a resource server running Punk::OAuth2::Checker accepts that token and honours the scope. A client registered without a secret authenticates on its client_id alone, so anyone who knows that identifier can request one.

NAME

Punk::OAuth2 - OAuth2 and OpenID Connect for Punk applications

VERSION

Version 0.01

SYNOPSIS

package MyApp;
use Punk;
use Punk::Plugin::OAuth2;

plugin 'OAuth2';

session secret => secret('session_key'), expires => '7d';

oauth2 google => {
	preset        => 'google',
	client_id     => secret('oauth.google_id'),
	client_secret => secret('oauth.google_secret'),
	scope         => 'openid email profile',
};

oauth2_login '/auth' => {
	on_login => 'Auth#on_login',
	base_url => 'https://app.example.com',
};

1;

DESCRIPTION

Punk::OAuth2 gives a Punk application the client side of OAuth2 and OpenID Connect: "Log in with ..." against Google, GitHub, or any OIDC provider, using the authorization code flow with PKCE, signed state, and id_token verification through Crypt::JWS.

The behaviour lives in Punk::Plugin::OAuth2; this module is the distribution's version anchor and documentation front door.

SEE ALSO

Punk::Plugin::OAuth2 - the plugin, keywords, and flow reference

Crypt::JWS - the signature engine

Punk - the web framework

AUTHOR

LNATION, <email at 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)