##---------------------------------------------------------------------------- ## Asynchronous HTTP Request and Promise - ~/lib/HTTP/Promise/Headers/ContentSecurityPolicy.pm ## Version v0.1.0 ## Copyright(c) 2022 DEGUEST Pte. Ltd. ## Author: Jacques Deguest ## Created 2022/05/07 ## Modified 2022/05/07 ## All rights reserved. ## ## ## This program is free software; you can redistribute it and/or modify it ## under the same terms as Perl itself. ##---------------------------------------------------------------------------- package HTTP::Promise::Headers::ContentSecurityPolicy; BEGIN { use strict; use warnings; use warnings::register; use parent qw( HTTP::Promise::Headers::Generic ); our $VERSION = 'v0.1.0'; }; use strict; use warnings; sub init { my $self = shift( @_ ); $self->{params} = []; $self->{properties} = {}; @_ = () if( @_ == 1 && $self->_is_a( $_[0] => 'Module::Generic::Null' ) ); if( @_ ) { my $this = shift( @_ ); my $ref = $self->_is_array( $this ) ? $this : [split( /(?params; my $props = $self->properties; foreach my $pair ( @$ref ) { my( $prop, $val ) = split( /[[:blank:]\h]+/, $pair, 2 ); $props->{ $prop } = $val; $params->push( $prop ); } } $self->{_init_strict_use_sub} = 1; $self->SUPER::init( @_ ) || return( $self->pass_error ); $self->_field_name( 'Content-Security-Policy' ); return( $self ); } sub as_string { return( shift->_set_get_properties_as_string( sep => ';', equal => ' ' ) ); } sub base_uri { return( shift->_set_get_property_value( 'base-uri', @_ ) ); } sub block_all_mixed_content { return( shift->_set_get_property_boolean( 'block-all-mixed-content', @_ ) ); } sub child_src { return( shift->_set_get_property_value( 'child-src', @_ ) ); } sub connect_src { return( shift->_set_get_property_value( 'connect-src', @_ ) ); } sub default_src { return( shift->_set_get_property_value( 'default-src', @_ ) ); } sub font_src { return( shift->_set_get_property_value( 'font-src', @_ ) ); } sub form_action { return( shift->_set_get_property_value( 'form-action', @_ ) ); } sub frame_ancestors { return( shift->_set_get_property_value( 'frame-ancestors', @_ ) ); } sub frame_src { return( shift->_set_get_property_value( 'frame-src', @_ ) ); } sub img_src { return( shift->_set_get_property_value( 'img-src', @_ ) ); } sub manifest_src { return( shift->_set_get_property_value( 'manifest-src', @_ ) ); } sub media_src { return( shift->_set_get_property_value( 'media-src', @_ ) ); } sub navigate_to { return( shift->_set_get_property_value( 'navigate-to', @_ ) ); } sub params { return( shift->_set_get_array_as_object( 'params', @_ ) ); } sub properties { return( shift->_set_get_hash_as_mix_object( 'properties', @_ ) ); } sub object_src { return( shift->_set_get_property_value( 'object-src', @_ ) ); } sub plugin_types { return( shift->_set_get_property_value( 'plugin-types', @_ ) ); } sub prefetch_src { return( shift->_set_get_property_value( 'prefetch-src', @_ ) ); } sub referrer { return( shift->_set_get_property_value( 'referrer', @_ ) ); } sub report_to { return( shift->_set_get_property_value( 'report-to', @_ ) ); } sub report_uri { return( shift->_set_get_property_value( 'report-uri', @_ ) ); } sub require_sri_for { return( shift->_set_get_property_value( 'require-sri-for', @_ ) ); } sub require_trusted_types_for { return( shift->_set_get_property_value( 'require-trusted-types-for', @_ ) ); } sub sandbox { return( shift->_set_get_property_value( 'sandbox', @_, { maybe_boolean => 1 } ) ); } sub script_src { return( shift->_set_get_property_value( 'script-src', @_ ) ); } sub script_src_elem { return( shift->_set_get_property_value( 'script-src-elem', @_ ) ); } sub script_src_attr { return( shift->_set_get_property_value( 'script-src-attr', @_ ) ); } sub style_src { return( shift->_set_get_property_value( 'style-src', @_ ) ); } sub style_src_attr { return( shift->_set_get_property_value( 'style-src-attr', @_ ) ); } sub style_src_elem { return( shift->_set_get_property_value( 'style-src-elem', @_ ) ); } sub trusted_types { return( shift->_set_get_property_value( 'trusted-types', @_, { maybe_boolean => 1 } ) ); } sub upgrade_insecure_requests { return( shift->_set_get_property_boolean( 'upgrade-insecure-requests', @_ ) ); } sub worker_src { return( shift->_set_get_property_value( 'worker-src', @_ ) ); } 1; # NOTE: POD __END__ =encoding utf-8 =head1 NAME HTTP::Promise::Headers::ContentSecurityPolicy - Content-Security-Policy Header Field =head1 SYNOPSIS use HTTP::Promise::Headers::ContentSecurityPolicy; my $csp = HTTP::Promise::Headers::ContentSecurityPolicy->new || die( HTTP::Promise::Headers::ContentSecurityPolicy->error, "\n" ); =head1 VERSION v0.1.0 =head1 DESCRIPTION The following description is taken from Mozilla documentation. 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). Content-Security-Policy: default-src 'self' Content-Security-Policy: default-src 'self' trusted.com *.trusted.com Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com Content-Security-Policy: default-src https://onlinebanking.example.com Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi =head1 METHODS 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 as a value. If nothing is provided, the current value is returned, or an empty string, but not C, if nothing is set yet. 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. $h->default_src( "'self'" ); # now: default-src 'self' $h->default_src( "'self' trusted.com *.trusted.com ); # now: default-src 'self' trusted.com *.trusted.com my $value = $h->default_src; # Remove it $h->default_src( undef ); You can get all the properties set by calling L, which returns an L =head2 as_string Returns a string representation of this header field value. =head2 base_uri Restricts the URLs which can be used in a document's element. Example: Content-Security-Policy: base-uri https://example.com/ Content-Security-Policy: base-uri https://example.com/ https://dev.example.com/ =head2 block_all_mixed_content You can still use this, but know its use is deprecated. Prevents loading any assets using HTTP when the page is loaded using HTTPS. Example: Content-Security-Policy: block-all-mixed-content; =head2 child_src Defines the valid sources for web workers and nested browsing contexts loaded using elements such as and