Bug 38365: Add Koha::Template::Plugin::Koha::CSPNonce

This patch adds a new Template plugin method, Koha.CSPNonce, that can be used to
attach the Content Security Policy nonce into our templates.

To test:
1. prove t/Koha/Middleware/ContentSecurityPolicy.t
2. prove t/db_dependent/Koha/Template/Plugin/Koha.t

Signed-off-by: David Cook <dcook@prosentient.com.au>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: David Cook <dcook@prosentient.com.au>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
This commit is contained in:
Lari Taskula 2026-01-16 15:02:13 +02:00 committed by Jonathan Druart
parent e160ed8b06
commit e750e6d1f5
No known key found for this signature in database
GPG Key ID: A085E712BEF0E0F0
4 changed files with 47 additions and 4 deletions

View File

@ -25,6 +25,7 @@ use C4::Context;
use Koha::Token;
use Koha;
use Koha::Cache::Memory::Lite;
use Koha::ContentSecurityPolicy;
=head1 NAME
@ -162,4 +163,16 @@ sub GenerateCSRF {
return $csrf_token;
}
=head3 CSPNonce
Retrieves the Content-Security-Policy nonce.
It should be cached by Koha::Middleware::ContentSecurityPolicy.
=cut
sub CSPNonce {
return Koha::ContentSecurityPolicy->new->nonce;
}
1;

View File

@ -24,11 +24,14 @@ use Test::NoWarnings;
use Test::More tests => 3;
use Test::Warn;
use File::Basename qw(dirname);
use HTTP::Request::Common;
use Plack::Builder;
use Plack::Util;
use Plack::Test;
use C4::Templates;
use t::lib::Mocks;
use_ok("Koha::Middleware::ContentSecurityPolicy");
@ -50,9 +53,13 @@ subtest 'test Content-Security-Policy header' => sub {
# Set nonce
Koha::ContentSecurityPolicy->new->nonce($test_nonce);
t::lib::Mocks::mock_config( 'opachtdocs', C4::Context->config('intranetdir') . '/t/mock_templates/opac-tmpl' );
my $env = {};
my $app = sub {
my $resp = [
require Koha::Plugins; # this should probably be "use Koha::Plugins;" in C4::Templates instead
my $template = C4::Templates::gettemplate( 'opac-csp.tt', 'opac' );
my $resp = [
200,
[
'Content-Type',
@ -60,7 +67,7 @@ subtest 'test Content-Security-Policy header' => sub {
'Content-Length',
12
],
[ Koha::ContentSecurityPolicy->new->nonce ]
[ $template->output ]
];
return $resp;
};
@ -79,7 +86,7 @@ subtest 'test Content-Security-Policy header' => sub {
"Response contains Content-Security-Policy header with the expected value"
);
is(
$res->content, $test_nonce,
$res->content, '<script nonce="' . $test_nonce . '">' . "\n" . '</script>' . "\n",
"Response contains generated nonce in the body"
);

View File

@ -17,7 +17,7 @@
use Modern::Perl;
use Test::More tests => 3;
use Test::More tests => 4;
use Template::Context;
use Template::Stash;
@ -79,3 +79,24 @@ subtest 'GenerateCSRF - New CSRF token generated every time we need one' => sub
$schema->storage->txn_rollback;
};
subtest 'CSPNonce' => sub {
plan tests => 1;
$schema->storage->txn_begin;
my $stash = Template::Stash->new( { sessionID => $session_id } );
my $context = Template::Context->new( { STASH => $stash } );
my $plugin = Koha::Template::Plugin::Koha->new($context);
my $csp = Koha::ContentSecurityPolicy->new;
my $nonce = $csp->nonce;
my $token = $plugin->CSPNonce;
is( $plugin->CSPNonce, $nonce, 'the correct nonce was provided' );
$schema->storage->txn_rollback;
};

View File

@ -0,0 +1,2 @@
[% USE raw %][% USE Koha %]<script nonce="[% Koha.CSPNonce | $raw %]">
</script>