File Coverage

lib/HTTP/Promise/Headers/ContentSecurityPolicy.pm
Criterion Covered Total %
statement 70 70 100.0
branch 5 8 62.5
condition 2 3 66.6
subroutine 42 42 100.0
pod 35 35 100.0
total 154 158 97.4


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## Asynchronous HTTP Request and Promise - ~/lib/HTTP/Promise/Headers/ContentSecurityPolicy.pm
3             ## Version v0.1.0
4             ## Copyright(c) 2022 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2022/05/07
7             ## Modified 2022/05/07
8             ## All rights reserved.
9             ##
10             ##
11             ## This program is free software; you can redistribute it and/or modify it
12             ## under the same terms as Perl itself.
13             ##----------------------------------------------------------------------------
14             package HTTP::Promise::Headers::ContentSecurityPolicy;
15             BEGIN
16             {
17 3     3   3618 use strict;
  3         81  
  3         106  
18 3     3   17 use warnings;
  3         7  
  3         85  
19 3     3   16 use warnings::register;
  3         7  
  3         360  
20 3     3   18 use parent qw( HTTP::Promise::Headers::Generic );
  3         5  
  3         15  
21 3     3   342 our $VERSION = 'v0.1.0';
22             };
23              
24 3     3   18 use strict;
  3         13  
  3         63  
25 3     3   14 use warnings;
  3         19  
  3         2999  
26              
27             sub init
28             {
29 7     7 1 8988 my $self = shift( @_ );
30 7         371 $self->{params} = [];
31 7         38 $self->{properties} = {};
32 7 50 66     68 @_ = () if( @_ == 1 && $self->_is_a( $_[0] => 'Module::Generic::Null' ) );
33 7 100       155 if( @_ )
34             {
35 5         14 my $this = shift( @_ );
36 5 50       27 my $ref = $self->_is_array( $this ) ? $this : [split( /(?<!\\)[[:blank:]\h]*\;[[:blank:]\h]*/, $this )];
37 5         148 my $params = $self->params;
38 5         4187 my $props = $self->properties;
39 5         6342 foreach my $pair ( @$ref )
40             {
41 39         299 my( $prop, $val ) = split( /[[:blank:]\h]+/, $pair, 2 );
42 39         126 $props->{ $prop } = $val;
43 39         859 $params->push( $prop );
44             }
45             }
46 7         52 $self->{_init_strict_use_sub} = 1;
47 7 50       49 $self->SUPER::init( @_ ) || return( $self->pass_error );
48 7         49 $self->_field_name( 'Content-Security-Policy' );
49 7         5635 return( $self );
50             }
51              
52 7     7 1 1286 sub as_string { return( shift->_set_get_properties_as_string( sep => ';', equal => ' ' ) ); }
53              
54 1     1 1 5 sub base_uri { return( shift->_set_get_property_value( 'base-uri', @_ ) ); }
55              
56 3     3 1 916 sub block_all_mixed_content { return( shift->_set_get_property_boolean( 'block-all-mixed-content', @_ ) ); }
57              
58 1     1 1 5 sub child_src { return( shift->_set_get_property_value( 'child-src', @_ ) ); }
59              
60 1     1 1 455 sub connect_src { return( shift->_set_get_property_value( 'connect-src', @_ ) ); }
61              
62 7     7 1 556 sub default_src { return( shift->_set_get_property_value( 'default-src', @_ ) ); }
63              
64 1     1 1 476 sub font_src { return( shift->_set_get_property_value( 'font-src', @_ ) ); }
65              
66 1     1 1 468 sub form_action { return( shift->_set_get_property_value( 'form-action', @_ ) ); }
67              
68 1     1 1 497 sub frame_ancestors { return( shift->_set_get_property_value( 'frame-ancestors', @_ ) ); }
69              
70 1     1 1 460 sub frame_src { return( shift->_set_get_property_value( 'frame-src', @_ ) ); }
71              
72 3     3 1 1009 sub img_src { return( shift->_set_get_property_value( 'img-src', @_ ) ); }
73              
74 1     1 1 468 sub manifest_src { return( shift->_set_get_property_value( 'manifest-src', @_ ) ); }
75              
76 3     3 1 1057 sub media_src { return( shift->_set_get_property_value( 'media-src', @_ ) ); }
77              
78 1     1 1 478 sub navigate_to { return( shift->_set_get_property_value( 'navigate-to', @_ ) ); }
79              
80 59     59 1 201 sub params { return( shift->_set_get_array_as_object( 'params', @_ ) ); }
81              
82 59     59 1 199 sub properties { return( shift->_set_get_hash_as_mix_object( 'properties', @_ ) ); }
83              
84 1     1 1 474 sub object_src { return( shift->_set_get_property_value( 'object-src', @_ ) ); }
85              
86 1     1 1 490 sub plugin_types { return( shift->_set_get_property_value( 'plugin-types', @_ ) ); }
87              
88 1     1 1 483 sub prefetch_src { return( shift->_set_get_property_value( 'prefetch-src', @_ ) ); }
89              
90 1     1 1 512 sub referrer { return( shift->_set_get_property_value( 'referrer', @_ ) ); }
91              
92 1     1 1 481 sub report_to { return( shift->_set_get_property_value( 'report-to', @_ ) ); }
93              
94 1     1 1 489 sub report_uri { return( shift->_set_get_property_value( 'report-uri', @_ ) ); }
95              
96 1     1 1 465 sub require_sri_for { return( shift->_set_get_property_value( 'require-sri-for', @_ ) ); }
97              
98 1     1 1 469 sub require_trusted_types_for { return( shift->_set_get_property_value( 'require-trusted-types-for', @_ ) ); }
99              
100 1     1 1 457 sub sandbox { return( shift->_set_get_property_value( 'sandbox', @_, { maybe_boolean => 1 } ) ); }
101              
102 3     3 1 580 sub script_src { return( shift->_set_get_property_value( 'script-src', @_ ) ); }
103              
104 1     1 1 505 sub script_src_elem { return( shift->_set_get_property_value( 'script-src-elem', @_ ) ); }
105              
106 1     1 1 458 sub script_src_attr { return( shift->_set_get_property_value( 'script-src-attr', @_ ) ); }
107              
108 1     1 1 450 sub style_src { return( shift->_set_get_property_value( 'style-src', @_ ) ); }
109              
110 1     1 1 448 sub style_src_attr { return( shift->_set_get_property_value( 'style-src-attr', @_ ) ); }
111              
112 1     1 1 518 sub style_src_elem { return( shift->_set_get_property_value( 'style-src-elem', @_ ) ); }
113              
114 1     1 1 470 sub trusted_types { return( shift->_set_get_property_value( 'trusted-types', @_, { maybe_boolean => 1 } ) ); }
115              
116 1     1 1 5 sub upgrade_insecure_requests { return( shift->_set_get_property_boolean( 'upgrade-insecure-requests', @_ ) ); }
117              
118 1     1 1 7 sub worker_src { return( shift->_set_get_property_value( 'worker-src', @_ ) ); }
119              
120             1;
121             # NOTE: POD
122             __END__
123              
124             =encoding utf-8
125              
126             =head1 NAME
127              
128             HTTP::Promise::Headers::ContentSecurityPolicy - Content-Security-Policy Header Field
129              
130             =head1 SYNOPSIS
131              
132             use HTTP::Promise::Headers::ContentSecurityPolicy;
133             my $csp = HTTP::Promise::Headers::ContentSecurityPolicy->new ||
134             die( HTTP::Promise::Headers::ContentSecurityPolicy->error, "\n" );
135              
136             =head1 VERSION
137              
138             v0.1.0
139              
140             =head1 DESCRIPTION
141              
142             The following description is taken from Mozilla documentation.
143              
144             The HTTP Content-Security-Policy response header allows web site administrators to control resources the user agent is allowed to load for a given page. With a few exceptions, policies mostly involve specifying server origins and script endpoints. This helps guard against cross-site scripting attacks (Cross-site_scripting).
145              
146             Content-Security-Policy: default-src 'self'
147             Content-Security-Policy: default-src 'self' trusted.com *.trusted.com
148             Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com
149             Content-Security-Policy: default-src https://onlinebanking.example.com
150             Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi
151              
152             =head1 METHODS
153              
154             All the methods below follow the same usage. You can pass a value to set it, whatever it is. It is up to you to proceed and set a value according to standards. The value will be added in order. To completely remove a property, simply pass C<undef> as a value. If nothing is provided, the current value is returned, or an empty string, but not C<undef>, if nothing is set yet.
155              
156             If you want to modify a value, you probably want to first fetch it, and set it back, unless you already what it should contain.
157              
158             $h->default_src( "'self'" ); # now: default-src 'self'
159             $h->default_src( "'self' trusted.com *.trusted.com ); # now: default-src 'self' trusted.com *.trusted.com
160             my $value = $h->default_src;
161             # Remove it
162             $h->default_src( undef );
163              
164             You can get all the properties set by calling L</params>, which returns an L<array object|Module::Generic::Array>
165              
166             =head2 as_string
167              
168             Returns a string representation of this header field value.
169              
170             =head2 base_uri
171              
172             Restricts the URLs which can be used in a document's <base> element.
173              
174             Example:
175              
176             Content-Security-Policy: base-uri https://example.com/
177             Content-Security-Policy: base-uri https://example.com/ https://dev.example.com/
178              
179             =head2 block_all_mixed_content
180              
181             You can still use this, but know its use is deprecated.
182              
183             Prevents loading any assets using HTTP when the page is loaded using HTTPS.
184              
185             Example:
186              
187             Content-Security-Policy: block-all-mixed-content;
188              
189             =head2 child_src
190              
191             Defines the valid sources for web workers and nested browsing contexts loaded using elements such as <frame> and <iframe>.
192              
193             Example:
194              
195             Content-Security-Policy: child-src https://example.com/
196             Content-Security-Policy: child-src https://example.com/ https://dev.example.com/
197              
198             =head2 connect_src
199              
200             Restricts the URLs which can be loaded using script interfaces.
201              
202             Example:
203              
204             Content-Security-Policy: connect-src https://example.com/
205              
206             =head2 default_src
207              
208             Serves as a fallback for the other fetch directives.
209              
210             Example:
211              
212             Content-Security-Policy: default-src 'self'
213              
214             =head2 font_src
215              
216             Specifies valid sources for fonts loaded using @font-face.
217              
218             Example:
219              
220             Content-Security-Policy: font-src https://example.com/
221              
222             =head2 form_action
223              
224             Restricts the URLs which can be used as the target of a form submissions from a given context.
225              
226             Example:
227              
228             Content-Security-Policy: form-action https://example.com/;
229             Content-Security-Policy: form-action https://example.com/ https://dev.example.com/;
230              
231             =head2 frame_ancestors
232              
233             Specifies valid parents that may embed a page using C<frame>, C<iframe>, C<object>, C<embed>, or C<applet>.
234              
235             Example:
236              
237             Content-Security-Policy: frame-ancestors https://example.com/;
238             Content-Security-Policy: frame-ancestors https://example.com/ https://dev.example.com/;
239              
240             =head2 frame_src
241              
242             Specifies valid sources for nested browsing contexts loading using elements such as <frame> and <iframe>.
243              
244             Example:
245              
246             Content-Security-Policy: frame-src https://example.com/
247              
248             =head2 img_src
249              
250             Specifies valid sources of images and favicons.
251              
252             Example:
253              
254             Content-Security-Policy: img-src https://example.com/
255             Content-Security-Policy: img-src 'self' img.example.com;
256              
257             =head2 manifest_src
258              
259             Specifies valid sources of application manifest files.
260              
261             Example:
262              
263             Content-Security-Policy: manifest-src https://example.com/
264              
265             =head2 media_src
266              
267             Specifies valid sources for loading media using the C<audio> , C<video> and C<track> elements.
268              
269             Example:
270              
271             Content-Security-Policy: media-src https://example.com/
272              
273             =head2 navigate_to
274              
275             Restricts the URLs to which a document can initiate navigation by any means, including <form> (if form-action is not specified), <a>, window.location, window.open, etc.
276              
277             Example:
278              
279             Content-Security-Policy: navigate-to https://example.com/;
280             Content-Security-Policy: navigate-to https://example.com/ https://dev.example.com/;
281              
282             =head2 object_src
283              
284             Specifies valid sources for the C<object>, C<embed>, and C<applet> elements.
285              
286             Example:
287              
288             Content-Security-Policy: object-src https://example.com/
289              
290             =head2 params
291              
292             Returns the L<array object|Module::Generic::Array> used by this header field object containing all the properties set.
293              
294             =head2 plugin_types
295              
296             You can still use this, but know its use is deprecated.
297              
298             Restricts the set of plugins that can be embedded into a document by limiting the types of resources which can be loaded.
299              
300             Example:
301              
302             Content-Security-Policy: plugin-types application/x-shockwave-flash
303              
304             =head2 prefetch_src
305              
306             Specifies valid sources to be prefetched or prerendered.
307              
308             Example:
309              
310             Content-Security-Policy: prefetch-src https://example.com/
311              
312             =head2 properties
313              
314             Sets or gets an hash or hash reference ot property-value pairs.
315              
316             =head2 referrer
317              
318             You can still use this, but know its use is deprecated and it is non-standard.
319              
320             Used to specify information in the Referer (sic) header for links away from a page. Use the C<Referrer-Policy> header instead.
321              
322             Example:
323              
324             Content-Security-Policy: referrer "none";
325              
326             You can set whatever value you want, but know that, according to rfc, the standard possible values are:
327              
328             =over 4
329              
330             =item C<no-referrer>
331              
332             The Referer header will be omitted entirely. No referrer information is sent along with requests.
333              
334             =item C<none-when-downgrade>
335              
336             This is the user agent's default behavior if no policy is specified. The origin is sent as referrer to a-priori as-much-secure destination (HTTPS->HTTPS), but is not sent to a less secure destination (HTTPS->HTTP).
337              
338             =item C<origin>
339              
340             Only send the origin of the document as the referrer in all cases. The document https://example.com/page.html will send the referrer https://example.com/.
341              
342             =item C<origin-when-cross-origin> / C<origin-when-crossorigin>
343              
344             Send a full URL when performing a same-origin request, but only send the origin of the document for other cases.
345              
346             =item C<unsafe-url>
347              
348             Send a full URL (stripped from parameters) when performing a same-origin or cross-origin request. This policy will leak origins and paths from TLS-protected resources to insecure origins. Carefully consider the impact of this setting.
349              
350             =back
351              
352             =head2 report_to
353              
354             Fires a SecurityPolicyViolationEvent.
355              
356             Example:
357              
358             Report-To: { "group": "csp-endpoint",
359             "max_age": 10886400,
360             "endpoints": [
361             { "url": "https://example.com/csp-reports" }
362             ] },
363             { "group": "hpkp-endpoint",
364             "max_age": 10886400,
365             "endpoints": [
366             { "url": "https://example.com/hpkp-reports" }
367             ] }
368             Content-Security-Policy: ...; report-to csp-endpoint
369              
370             =head2 report_uri
371              
372             Instructs the user agent to report attempts to violate the Content Security Policy. These violation reports consist of JSON documents sent via an HTTP POST request to the specified URI.
373              
374             Example:
375              
376             Content-Security-Policy: default-src https:; report-uri /csp-violation-report-endpoint/
377             Content-Security-Policy: default-src https:; report-uri /csp-violation-report-endpoint/ https://dev.example.com/report;
378              
379             =head2 require_sri_for
380              
381             Requires the use of SRI for scripts or styles on the page.
382              
383             Example:
384              
385             Content-Security-Policy: require-sri-for script;
386             Content-Security-Policy: require-sri-for style;
387             Content-Security-Policy: require-sri-for script style;
388              
389             =head2 require_trusted_types_for
390              
391             Enforces Trusted Types at the DOM XSS injection sinks.
392              
393             Example:
394              
395             Content-Security-Policy: require-trusted-types-for 'script';
396              
397             =head2 sandbox
398              
399             Enables a sandbox for the requested resource similar to the C<iframe> sandbox attribute.
400              
401             This can be set as a boolean or with a string value:
402              
403             # This will add 'sandbox' (without surrounding quotes) as a property
404             $h->sandbox(1);
405             # Returns true.
406             my $rv = $h->sandbox;
407             $h->sandbox(0);
408             # Returns false.
409             my $rv = $h->sandbox;
410             # Removes it
411             $h->sandbox( undef );
412             # Will set sandbox to 'allow-downloads' (without surrounding quotes)
413             $h->sandbox( 'allow-downloads' );
414              
415             It takes an optional value, such as:
416              
417             =over 4
418              
419             =item C<allow-downloads>
420              
421             Allows for downloads after the user clicks a button or link.
422              
423             =item C<allow-downloads-without-user-activation>
424              
425             This is reportedly an experimental value.
426              
427             Allows for downloads to occur without a gesture from the user.
428              
429             =item C<allow-forms>
430              
431             Allows the page to submit forms. If this keyword is not used, this operation is not allowed.
432              
433             =item C<allow-modals>
434              
435             Allows the page to open modal windows.
436              
437             =item C<allow-orientation-lock>
438              
439             Allows the page to disable the ability to lock the screen orientation.
440              
441             =item C<allow-pointer-lock>
442              
443             Allows the page to use the Pointer Lock API.
444              
445             =item C<allow-popups>
446              
447             Allows popups (like from window.open, target="_blank", showModalDialog). If this keyword is not used, that functionality will silently fail.
448              
449             =item C<allow-popups-to-escape-sandbox>
450              
451             Allows a sandboxed document to open new windows without forcing the sandboxing flags upon them. This will allow, for example, a third-party advertisement to be safely sandboxed without forcing the same restrictions upon the page the ad links to.
452              
453             =item C<allow-presentation>
454              
455             Allows embedders to have control over whether an iframe can start a presentation session.
456              
457             =item C<allow-same-origin>
458              
459             Allows the content to be treated as being from its normal origin. If this keyword is not used, the embedded content is treated as being from a unique origin.
460              
461             =item C<allow-scripts>
462              
463             Allows the page to run scripts (but not create pop-up windows). If this keyword is not used, this operation is not allowed.
464              
465             =item C<allow-storage-access-by-user-activation>
466              
467             This is reportedly an experimental value.
468              
469             Lets the resource request access to the parent's storage capabilities with the Storage Access API.
470              
471             =item C<allow-top-navigation>
472              
473             Allows the page to navigate (load) content to the top-level browsing context. If this keyword is not used, this operation is not allowed.
474              
475             =item C<allow-top-navigation-by-user-activation>
476              
477             Lets the resource navigate the top-level browsing context, but only if initiated by a user gesture.
478              
479             =back
480              
481             Example:
482              
483             Content-Security-Policy: sandbox;
484             Content-Security-Policy: sandbox allow-scripts;
485              
486             =head2 script_src
487              
488             Specifies valid sources for JavaScript.
489              
490             Example:
491              
492             Content-Security-Policy: script-src https://example.com/
493             Content-Security-Policy: script-src 'self' js.example.com;
494              
495             =head2 script_src_elem
496              
497             Specifies valid sources for JavaScript <script> elements.
498              
499             Example:
500              
501             Content-Security-Policy: script-src-elem https://example.com/
502             Content-Security-Policy: script-src-elem https://example.com/ https://dev.example.com/
503              
504             =head2 script_src_attr
505              
506             Specifies valid sources for JavaScript inline event handlers.
507              
508             Example:
509              
510             Content-Security-Policy: script-src-attr https://example.com/
511             Content-Security-Policy: script-src-attr https://example.com/ https://dev.example.com/
512              
513             =head2 style_src
514              
515             Specifies valid sources for stylesheets.
516              
517             Example:
518              
519             Content-Security-Policy: style-src https://example.com/
520             Content-Security-Policy: style-src https://example.com/ https://dev.example.com/
521             Content-Security-Policy: style-src 'self' css.example.com;
522              
523             =head2 style_src_attr
524              
525             Specifies valid sources for inline styles applied to individual DOM elements.
526              
527             Example:
528              
529             Content-Security-Policy: style-src-attr https://example.com/
530             Content-Security-Policy: style-src-attr https://example.com/ https://dev.example.com/
531              
532             =head2 style_src_elem
533              
534             Specifies valid sources for stylesheets <style> elements and <link> elements with rel="stylesheet".
535              
536             Example:
537              
538             Content-Security-Policy: script-src-elem https://example.com/
539             Content-Security-Policy: script-src-elem https://example.com/ https://dev.example.com/
540              
541             =head2 trusted_types
542              
543             Used to specify an allow-list of Trusted Types policies. Trusted Types allows applications to lock down DOM XSS injection sinks to only accept non-spoofable, typed values in place of strings.
544              
545             Just like L</sandbox>, this can be set as a boolean or with a string value.
546              
547             Example:
548              
549             # Set it as a boolean value
550             $h->trusted_types(1);
551             Content-Security-Policy: trusted-types;
552             # Set it as a string value
553             # You need to set the surrounding single quotes yourself
554             $h->trusted_types( "'none'" );
555             Content-Security-Policy: trusted-types 'none';
556             # Set it to foo
557             $h->trusted_types( 'foo' );
558             Content-Security-Policy: trusted-types foo;
559             Content-Security-Policy: trusted-types foo bar 'allow-duplicates';
560              
561             =head2 upgrade_insecure_requests
562              
563             Instructs user agents to treat all of a site's insecure URLs (those served over HTTP) as though they have been replaced with secure URLs (those served over HTTPS). This directive is intended for web sites with large numbers of insecure legacy URLs that need to be rewritten.
564              
565             Example:
566              
567             Content-Security-Policy: upgrade-insecure-requests;
568              
569             =head2 worker_src
570              
571             Specifies valid sources for Worker, SharedWorker, or ServiceWorker scripts.
572              
573             Example:
574              
575             Content-Security-Policy: worker-src https://example.com/
576             Content-Security-Policy: worker-src https://example.com/ https://dev.example.com/
577              
578             =head1 AUTHOR
579              
580             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
581              
582             =head1 SEE ALSO
583              
584             L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy> and L<Mozilla on CSP|https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>
585              
586             L<https://content-security-policy.com/>
587              
588             L<HTTP::Promise>, L<HTTP::Promise::Request>, L<HTTP::Promise::Response>, L<HTTP::Promise::Message>, L<HTTP::Promise::Entity>, L<HTTP::Promise::Headers>, L<HTTP::Promise::Body>, L<HTTP::Promise::Body::Form>, L<HTTP::Promise::Body::Form::Data>, L<HTTP::Promise::Body::Form::Field>, L<HTTP::Promise::Status>, L<HTTP::Promise::MIME>, L<HTTP::Promise::Parser>, L<HTTP::Promise::IO>, L<HTTP::Promise::Stream>, L<HTTP::Promise::Exception>
589              
590             =head1 COPYRIGHT & LICENSE
591              
592             Copyright(c) 2022 DEGUEST Pte. Ltd.
593              
594             All rights reserved.
595              
596             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
597              
598             =cut