File Coverage

blib/lib/Plack/Middleware/BlockHeaderInjection.pm
Criterion Covered Total %
statement 33 33 100.0
branch 6 6 100.0
condition 1 2 50.0
subroutine 9 9 100.0
pod 1 2 50.0
total 50 52 96.1


line stmt bran cond sub pod time code
1             package Plack::Middleware::BlockHeaderInjection;
2              
3             # ABSTRACT: block header injections in responses
4              
5 3     3   2076 use v5.12;
  3         17  
6 3     3   16 use warnings;
  3         7  
  3         96  
7              
8 3     3   449 use parent qw( Plack::Middleware );
  3         314  
  3         16  
9              
10 3     3   13167 use Plack::Util;
  3         6  
  3         69  
11 3     3   15 use Plack::Util::Accessor qw( logger status );
  3         22  
  3         14  
12              
13             our $VERSION = 'v1.1.0';
14              
15              
16             sub call {
17 6     6 1 58757 my ( $self, $env ) = @_;
18              
19             # cache the logger
20       2     $self->logger( $env->{'psgix.logger'} || sub { } )
21 6 100 50     24 unless defined $self->logger;
22              
23 6 100       175 $self->status(500) unless $self->status;
24              
25 6         55 my $res = $self->app->($env);
26              
27             Plack::Util::response_cb(
28             $res,
29             sub {
30 6     6   122 my $res = shift;
31              
32             # Sanity check headers
33              
34 6         12 my $hdrs = $res->[1];
35              
36 6         12 my $i = 0;
37 6         9 while ( $i < @{$hdrs} ) {
  16         62  
38 10         24 my $val = $hdrs->[ $i + 1 ];
39 10 100       34 if ( $val =~ /[\n\r]/ ) {
40 2         6 my $key = $hdrs->[$i];
41 2         10 $self->log( error => "possible header injection detected in ${key}" );
42 2         7 $res->[0] = $self->status;
43 2         12 Plack::Util::header_remove( $hdrs, $key );
44             }
45 10         79 $i += 2;
46             }
47              
48             }
49 6         2358 );
50              
51             }
52              
53             # Note: ideas borrowed from XSRFBlock
54              
55              
56             sub log {
57 2     2 0 5 my ( $self, $level, $msg ) = @_;
58 2         42 $self->logger->(
59             {
60             level => $level,
61             message => "BlockHeaderInjection: ${msg}",
62             }
63             );
64             }
65              
66              
67             1;
68              
69             __END__