Current section
Files
Jump to
Current section
Files
src/lib/wf_security_policy.erl
% vim: sw=4 ts=4 et ft=erlang
-module(wf_security_policy).
-include("wf.hrl").
-export([
generate/0
, nonce/0
]).
generate() ->
case wf:config_default(content_security_policy, []) of
[] ->
undefined;
Spec ->
build_csp(Spec)
end.
build_csp(Spec) when is_list(Spec) ->
lists:foldl(fun process_csp_rule/2, [], Spec);
build_csp(Spec) ->
Spec.
process_csp_rule({Domain, Sources}, Acc) ->
NormalizedSources = string:join([source(S) || S <- Sources], " "),
domain(Domain) ++ " " ++ NormalizedSources ++ "; " ++ Acc.
%% create a random nonce value; hard coded to be 12 characters
nonce() ->
Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
Length = length(Chars),
lists:foldl(
fun(_, Acc) ->
[lists:nth(rand:uniform(Length), Chars)] ++ Acc
end, [], lists:seq(1, 12)).
%% allow atomized aliases for CSP domains
domain(default_src) -> "default-src";
domain(script_src) -> "script-src";
domain(style_src) -> "style-src";
domain(img_src) -> "img-src";
domain(connect_src) -> "connect-src";
domain(font_src) -> "font-src";
domain(object_src) -> "object-src";
domain(media_src) -> "media-src";
domain(frame_src) -> "frame-src";
domain(sandbox) -> "sandbox";
domain(report_uri) -> "report-uri";
domain(child_src) -> "child-src";
domain(form_action) -> "form-action";
domain(frame_ancestors) -> "frame-ancestors";
domain(plugin_types) -> "plugin-types";
domain(base_uri) -> "base-uri";
domain(report_to) -> "report-to";
domain(worker_src) -> "worker-src";
domain(manifest_src) -> "manifest-src";
domain(prefetch_src) -> "prefetch-src";
domain(navigate_to) -> "navigate-to";
domain(Domain) -> Domain.
%% allow atomized aliases for CSP sources
source(none) -> "'none'";
source(self) -> "'self'";
source(data) -> "'data:'";
source(https) -> "'https:'";
source(unsafe_inline) -> "'unsafe-inline'";
source(unsafe_eval) -> "'unsafe-eval'";
source(strict_dynamic) -> "'strict-dynamic'";
source(unsafe_hashes) -> "'unsafe-hashes'";
source(nonce) -> "'nonce-" ++ wf:script_nonce() ++ "'";
source(Source) -> Source.