-define(deprecated, true).
%-undef(depreceted).
-include("deprecated.hrl").

-define(TAINTEDCHECKERS, tainted_app_arg => ?TAINTEDFUNS).
-define(TAINTEDFUNS, [fun exported/1, fun unknown/1, fun explicit_fun_pattern/1]).

-define(VULNERABILITIES,
    [#{desc_type => funapp, type => race_condition, kind => link, target => {erlang, link, 1}, argindex => 1, tainted_app_arg => [fun spawn_location/1], desc => "Unsafe process linkage with erlang:link/1."},
    
     #{desc_type => funapp, type => race_condition, kind => prioritisation, target => {erlang, process_flag, 2}, argindex => 1, tainted_app_arg => [fun process_priority/1 | ?TAINTEDFUNS], severity_fun => fun priority/1, desc => "Unsafe process priority modification."},
    
     #{desc_type => funapp, type => race_condition, kind => ets, target => {ets, first, 1}, argindex => none, tainted_app_arg => [], sanitiser => fun fixed_table/1, desc => "Traversed ets table is not fixed."},
     #{desc_type => funapp, type => race_condition, kind => ets, target => {ets, next, 2}, argindex => none, tainted_app_arg => [], sanitiser => fun fixed_table/1, desc => "Traversed ets table is not fixed."},
     #{desc_type => funapp, type => race_condition, kind => ets, target => {ets, select, 1}, argindex => none, tainted_app_arg => [], sanitiser => fun fixed_table/1, desc => "Traversed ets table is not fixed."},
     #{desc_type => funapp, type => race_condition, kind => ets, target => {ets, select, 3}, argindex => none, tainted_app_arg => [], sanitiser => fun fixed_table/1, desc => "Traversed ets table is not fixed."},
     #{desc_type => funapp, type => race_condition, kind => ets, target => {ets, match, 1}, argindex => none, tainted_app_arg => [], sanitiser => fun fixed_table/1, desc => "Traversed ets table is not fixed."},
     #{desc_type => funapp, type => race_condition, kind => ets, target => {ets, match, 3}, argindex => none, tainted_app_arg => [], sanitiser => fun fixed_table/1, desc => "Traversed ets table is not fixed."},
     #{desc_type => funapp, type => race_condition, kind => ets, target => {ets, match_object, 1}, argindex => none, tainted_app_arg => [], sanitiser => fun fixed_table/1, desc => "Traversed ets table is not fixed."},
     #{desc_type => funapp, type => race_condition, kind => ets, target => {ets, match_object, 3}, argindex => none, tainted_app_arg => [], sanitiser => fun fixed_table/1, desc => "Traversed ets table is not fixed."},
     #{desc_type => funapp, type => race_condition, kind => ets, target => {ets, slot, 2}, argindex => none, tainted_app_arg => [], sanitiser => fun fixed_table/1, desc => "Traversed ets table is not fixed."},

     #{desc_type => funapp, type => injection, kind => os, target => {os, cmd, 1},    argindex => 1,   ?TAINTEDCHECKERS, desc => "Unsafe os:cmd/1 usage."},
     #{desc_type => funapp, type => injection, kind => os, target => {os, cmd, 2},    argindex => 1,   ?TAINTEDCHECKERS, desc => "Unsafe os:cmd/2 usage."},
     #{desc_type => funapp, type => injection, kind => os, target => {os, putenv, 2}, argindex => all, ?TAINTEDCHECKERS, desc => "Unsafe environment setting with os:putenv/2."},

     % check [{env, ...}]
     #{desc_type => funapp, type => injection, kind => port, target => {erlang, open_port, 2}, argindex => {1, {tuple, 2}}, ?TAINTEDCHECKERS, severity_fun => fun executable_env/1, desc => "Unsafe erlang:open_port/2 usage."},
     
     #{desc_type => funapp, type => injection, kind => nif, target => {erlang, load_nif, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe erlang:load_nif/2 usage."},

     #{desc_type => funapp, type => injection, kind => port_driver, target => {erl_ddll, load, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe erl_ddll:load/2 usage."},
     #{desc_type => funapp, type => injection, kind => port_driver, target => {erl_ddll, load_driver, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe erl_ddll:load_driver/2 usage."},
     #{desc_type => funapp, type => injection, kind => port_driver, target => {erl_ddll, reload, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe erl_ddll:reload/2 usage."},
     #{desc_type => funapp, type => injection, kind => port_driver, target => {erl_ddll, reload_driver, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe erl_ddll:reload_driver/2 usage."},
     #{desc_type => funapp, type => injection, kind => port_driver, target => {erl_ddll, try_load, 3}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe erl_ddll:try_load/3 usage."},

     #{desc_type => funapp, type => injection, kind => file_eval, target => {file, eval, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe file:eval/1 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval, target => {file, eval, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe file:eval/2 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval, target => {file, path_eval, 2}, argindex => all, ?TAINTEDCHECKERS, desc => "Unsafe file:path_eval/2 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval, target => {file, path_script, 2}, argindex => all, ?TAINTEDCHECKERS, desc => "Unsafe file:path_script/2 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval, target => {file, path_script, 3}, argindex => [1,2], ?TAINTEDCHECKERS, desc => "Unsafe file:path_script/3 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval, target => {file, script, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe file:script/1 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval, target => {file, script, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe file:script/1 usage."},

     #{desc_type => funapp, type => injection, kind => compile_load, target => {compile, file, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe compile:file/1 usage."},
     #{desc_type => funapp, type => injection, kind => compile_load, target => {compile, file, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe compile:file/2 usage."},
     #{desc_type => funapp, type => injection, kind => compile_load, target => {compile, noenv_file, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe compile:noenv_file/2 usage."},
     #{desc_type => funapp, type => injection, kind => compile_load, target => {code, atomic_load, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe code:atomic_load/1 usage."},
     #{desc_type => funapp, type => injection, kind => compile_load, target => {code, load_abs, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe code:load_abs/1 usage."},
     #{desc_type => funapp, type => injection, kind => compile_load, target => {code, load_abs, 2}, argindex => [1,2], ?TAINTEDCHECKERS, desc => "Unsafe code:load_abs/2 usage (undocumented function)."},
     #{desc_type => funapp, type => injection, kind => compile_load, target => {code, load_binary, 3}, argindex => 3, ?TAINTEDCHECKERS, desc => "Unsafe code:load_binary/3 usage."},
     #{desc_type => funapp, type => injection, kind => compile_load, target => {code, load_file, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe code:load_file/1 usage."},
     
     #{desc_type => funapp, type => dos, kind => atom_exhaustion, target => {erlang, list_to_atom, 1}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun member_filter/1, severity_fun => fun iteration/1, desc => "Unsafe atom generation with list_to_atom/1."},
     #{desc_type => funapp, type => dos, kind => atom_exhaustion, target => {erlang, binary_to_term, 1}, argindex => 1, ?TAINTEDCHECKERS, severity_fun => fun iteration/1, desc => "Unsafe atom generation with binary_to_term/1."},
     #{desc_type => funapp, type => dos, kind => atom_exhaustion, target => {erlang, binary_to_term, 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun safe_option/1, severity_fun => fun iteration/1, desc => "Unsafe atom generation with binary_to_term/2."},
     #{desc_type => funapp, type => dos, kind => atom_exhaustion, target => {erlang, binary_to_atom, 1}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun member_filter/1, severity_fun => fun iteration/1, desc => "Unsafe atom generation with binary_to_atom/1."},
     #{desc_type => funapp, type => dos, kind => atom_exhaustion, target => {erlang, binary_to_atom, 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun member_filter/1, severity_fun => fun iteration/1, desc => "Unsafe atom generation with binary_to_atom/2."},

     #{desc_type => funapp, type => dos, kind => file_read_atom_exhaustion, target => {file, consult, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe file:consult/1 usage."},
     #{desc_type => funapp, type => dos, kind => file_read_atom_exhaustion, target => {file, path_consult, 2}, argindex => all, ?TAINTEDCHECKERS, desc => "Unsafe file:path_consult/2 usage."},
     
     #{desc_type => funapp, type => dos, kind => xml_atom_exhaustion, target => {xmerl_scan, file, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe atom generation with xmerl_scan:file/1."},
     #{desc_type => funapp, type => dos, kind => xml_atom_exhaustion, target => {xmerl_scan, file, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe atom generation with xmerl_scan:file/2."},
     #{desc_type => funapp, type => dos, kind => xml_atom_exhaustion, target => {xmerl_scan, string, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe atom generation with xmerl_scan:string/1."},
     #{desc_type => funapp, type => dos, kind => xml_atom_exhaustion, target => {xmerl_scan, string, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe atom generation with xmerl_scan:string/2."},

     %% removed in OTP25
     #{desc_type => funapp, type => dos, kind => http_uri_atom_exhaustion, target => {http_uri, parse, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe atom generation with http_uri:parse/1."},
     #{desc_type => funapp, type => dos, kind => http_uri_atom_exhaustion, target => {http_uri, parse, 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun scheme_validation/1, desc => "Unsafe atom generation with http_uri:parse/2."},

     %% it is more than a dos
     #{desc_type => funapp, type => dos, kind => xxe_attack, target => {xmerl_sax_parser, file, 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun disabled_expansion/1, desc => "Entity expansion can lead to exponential expansion with xmerl_sax_parser:file/2."},
     #{desc_type => funapp, type => dos, kind => xxe_attack, target => {xmerl_sax_parser, stream, 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun disabled_expansion/1, desc => "Entity expansion can lead to exponential expansion with xmerl_sax_parser:stream/2."},

     #{desc_type => funapp, type => dos, kind => network, target => {net_kernel, allow, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe net_kernel:allow/1 usage."},
     
     % server only API warning is not needed: ssl:handshake/1,2,3 and listen/2
     #{desc_type => funapp, type => mitm, kind => ssl_peer_verification, target => {ssl, connect, 2}, argindex => 2, tainted_app_arg => [], sanitiser => fun verify_peer/1, desc => "TLS client's should set {verify, verify_peer} to avoid ignoring server certificates!"},
     #{desc_type => funapp, type => mitm, kind => ssl_peer_verification, target => {ssl, connect, 3}, argindex => [2, 3], tainted_app_arg => [], sanitiser => fun verify_peer/1, desc => "TLS client's should set {verify, verify_peer} to avoid ignoring server certificates!"},
     #{desc_type => funapp, type => mitm, kind => ssl_peer_verification, target => {ssl, connect, 4}, argindex => 3, tainted_app_arg => [], sanitiser => fun verify_peer/1, desc => "TLS client's should set {verify, verify_peer} to avoid ignoring server certificates!"},
     #{desc_type => funapp, type => mitm, kind => ssl_peer_verification, target => {ssl, handshake_continue, 2}, argindex => 2, tainted_app_arg => [], sanitiser => fun verify_peer/1, desc => "TLS client's should set {verify, verify_peer} to avoid ignoring server certificates!"},
     #{desc_type => funapp, type => mitm, kind => ssl_peer_verification, target => {ssl, handshake_continue, 3}, argindex => 2, tainted_app_arg => [], sanitiser => fun verify_peer/1, desc => "TLS client's should set {verify, verify_peer} to avoid ignoring server certificates!"},

     % client only API warning is not needed: connect/2,3,4
     #{desc_type => funapp, type => dos, kind => ssl_client_renegotiation, target => {ssl, handshake, 2}, argindex => 2, tainted_app_arg => [], sanitiser => fun disabled_renegotiation/1, desc => "TLS servers should strictly disable client-initiated renegotiation."},
     #{desc_type => funapp, type => dos, kind => ssl_client_renegotiation, target => {ssl, handshake, 3}, argindex => 2, tainted_app_arg => [], sanitiser => fun disabled_renegotiation/1, desc => "TLS servers should strictly disable client-initiated renegotiation."},
     #{desc_type => funapp, type => dos, kind => ssl_client_renegotiation, target => {ssl, handshake_continue, 2}, argindex => 2, tainted_app_arg => [], sanitiser => fun disabled_renegotiation/1, desc => "TLS servers should strictly disable client-initiated renegotiation."},
     #{desc_type => funapp, type => dos, kind => ssl_client_renegotiation, target => {ssl, handshake_continue, 3}, argindex => 2, tainted_app_arg => [], sanitiser => fun disabled_renegotiation/1, desc => "TLS servers should strictly disable client-initiated renegotiation."},
     #{desc_type => funapp, type => dos, kind => ssl_client_renegotiation, target => {ssl, listen, 2}, argindex => 2, tainted_app_arg => [], sanitiser => fun disabled_renegotiation/1, desc => "TLS servers should strictly disable client-initiated renegotiation."},

     #{desc_type => funapp, type => mitm, kind => poodle_attack, target => {ssl, listen, 2}, argindex => 2, tainted_app_arg => [fun padding_check/1], desc => "Using {padding_check, false} makes TLS vulnerable to the Poodle attack."},
     #{desc_type => funapp, type => mitm, kind => poodle_attack, target => {ssl, connect, 2}, argindex => 2, tainted_app_arg => [fun padding_check/1], desc => "Using {padding_check, false} makes TLS vulnerable to the Poodle attack."},
     #{desc_type => funapp, type => mitm, kind => poodle_attack, target => {ssl, connect, 3}, argindex => [2, 3], tainted_app_arg => [fun padding_check/1], desc => "Using {padding_check, false} makes TLS vulnerable to the Poodle attack."},
     #{desc_type => funapp, type => mitm, kind => poodle_attack, target => {ssl, connect, 4}, argindex => 2, tainted_app_arg => [fun padding_check/1], desc => "Using {padding_check, false} makes TLS vulnerable to the Poodle attack."},
     #{desc_type => funapp, type => mitm, kind => poodle_attack, target => {ssl, handshake_continue, 2}, argindex => 2, tainted_app_arg => [fun padding_check/1], desc => "Using {padding_check, false} makes TLS vulnerable to the Poodle attack."},
     #{desc_type => funapp, type => mitm, kind => poodle_attack, target => {ssl, handshake_continue, 3}, argindex => 2, tainted_app_arg => [fun padding_check/1], desc => "Using {padding_check, false} makes TLS vulnerable to the Poodle attack."},
     #{desc_type => funapp, type => mitm, kind => poodle_attack, target => {ssl, handshake, 2}, argindex => 2, tainted_app_arg => [fun padding_check/1], desc => "Using {padding_check, false} makes TLS vulnerable to the Poodle attack."},
     #{desc_type => funapp, type => mitm, kind => poodle_attack, target => {ssl, handshake, 3}, argindex => 2, tainted_app_arg => [fun padding_check/1], desc => "Using {padding_check, false} makes TLS vulnerable to the Poodle attack."},

     #{desc_type => funapp, type => mitm, kind => beast_attack, target => {ssl, listen, 2}, argindex => 2, tainted_app_arg => [fun beast_mitigation_check/1], desc => "Using {beast_mitigation, disabled} makes TLS-1.0 vulnerable to the BEAST attack."},
     #{desc_type => funapp, type => mitm, kind => beast_attack, target => {ssl, connect, 2}, argindex => 2, tainted_app_arg => [fun beast_mitigation_check/1], desc => "Using {beast_mitigation, disabled} makes TLS-1.0 vulnerable to the BEAST attack."},
     #{desc_type => funapp, type => mitm, kind => beast_attack, target => {ssl, connect, 3}, argindex => [2, 3], tainted_app_arg => [fun beast_mitigation_check/1], desc => "Using {beast_mitigation, disabled} makes TLS-1.0 vulnerable to the BEAST attack."},
     #{desc_type => funapp, type => mitm, kind => beast_attack, target => {ssl, connect, 4}, argindex => 2, tainted_app_arg => [fun beast_mitigation_check/1], desc => "Using {beast_mitigation, disabled} makes TLS-1.0 vulnerable to the BEAST attack."},
     #{desc_type => funapp, type => mitm, kind => beast_attack, target => {ssl, handshake_continue, 2}, argindex => 2, tainted_app_arg => [fun beast_mitigation_check/1], desc => "Using {beast_mitigation, disabled} makes TLS-1.0 vulnerable to the BEAST attack."},
     #{desc_type => funapp, type => mitm, kind => beast_attack, target => {ssl, handshake_continue, 3}, argindex => 2, tainted_app_arg => [fun beast_mitigation_check/1], desc => "Using {beast_mitigation, disabled} makes TLS-1.0 vulnerable to the BEAST attack."},
     #{desc_type => funapp, type => mitm, kind => beast_attack, target => {ssl, handshake, 2}, argindex => 2, tainted_app_arg => [fun beast_mitigation_check/1], desc => "Using {beast_mitigation, disabled} makes TLS-1.0 vulnerable to the BEAST attack."},
     #{desc_type => funapp, type => mitm, kind => beast_attack, target => {ssl, handshake, 3}, argindex => 2, tainted_app_arg => [fun beast_mitigation_check/1], desc => "Using {beast_mitigation, disabled} makes TLS-1.0 vulnerable to the BEAST attack."},


     % Old crypto functions - deprecated from 23.0 and removed from OTP 24.0
     #{desc_type => funapp, type => mitm, kind => old_crypto_api, target => {crypto, ?OLDCRYPTOFUNS}, argindex => none, tainted_app_arg => [], desc => "Old, deprecated (removed in OTP25) crypto calls!"},

     #{desc_type => funapp, type => mitm, kind => deprecated_crypto_api, target => {crypto, ?DEPRECATEDCRYPTOFUNS}, argindex => none, tainted_app_arg => [], desc => "Deprecated, unsafe crypto calls!"},
     #{desc_type => funapp, type => mitm, kind => unsafe_crypto_api, target => {crypto, ?UNSAFECRYPTOFUNS}, argindex => none, tainted_app_arg => [], desc => "Unsafe low level functions for operations with asymmetrical keys!"},
     
     #{desc_type => funapp, type => mitm, kind => network, target => {net_kernel, connect_node, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe net_kernel:connect_node/1 usage."},
     #{desc_type => funapp, type => mitm, kind => network, target => {net_kernel, start, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe net_kernel:start/1 usage."},
     #{desc_type => funapp, type => mitm, kind => network, target => {net_kernel, start, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe net_kernel:start/2 usage."},

     #{desc_type => funapp, type => info_breach, kind => network, target => {net_adm, host_file, 0}, argindex => none, tainted_app_arg => [], desc => "Unsafe net_adm:host_file/0 usage."},
     #{desc_type => funapp, type => info_breach, kind => network, target => {net_adm, world, 0}, argindex => none, tainted_app_arg => [], desc => "Unsafe net_adm:world/0 usage."}, %% ??? DOS
     #{desc_type => funapp, type => info_breach, kind => network, target => {net_adm, world, 1}, argindex => none, tainted_app_arg => [], desc => "Unsafe net_adm:world/1 usage."}, %% ??? DOS
     #{desc_type => funapp, type => info_breach, kind => network, target => {net_adm, world_list, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe net_adm:world_list/1 usage."}, %% ??? DOS
     #{desc_type => funapp, type => info_breach, kind => network, target => {net_adm, world_list, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe net_adm:world_list/2 usage."}, %% ??? DOS
     #{desc_type => funapp, type => info_breach, kind => network, target => {net_adm, world_list, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe net_adm:world_list/2 usage."} %% ??? DOS
    
    ]

     ++

    [
     #{desc_type => funapp, type => injection, kind => port_ex, target => {'Elixir.System', shell, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.System':shell/1 usage."},
     #{desc_type => funapp, type => injection, kind => port_ex, target => {'Elixir.System', shell, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.System':shell/2 usage."},
     #{desc_type => funapp, type => injection, kind => port_ex, target => {'Elixir.System', cmd, 2}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.System':cmd/2 usage."},
     #{desc_type => funapp, type => injection, kind => port_ex, target => {'Elixir.System', cmd, 3}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.System':cmd/3 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval_ex, target => {'Elixir.Code', eval_file, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Code':eval_file/1 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval_ex, target => {'Elixir.Code', eval_file, 2}, argindex => all, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Code':eval_file/2 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval_ex, target => {'Elixir.Code', eval_string, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Code':eval_string/1 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval_ex, target => {'Elixir.Code', eval_string, 2}, argindex => all, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Code':eval_string/2 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval_ex, target => {'Elixir.Code', eval_string, 3}, argindex => all, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Code':eval_string/3 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval_ex, target => {'Elixir.Code', eval_quoted, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Code':eval_quoted/1 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval_ex, target => {'Elixir.Code', eval_quoted, 2}, argindex => all, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Code':eval_quoted/2 usage."},
     #{desc_type => funapp, type => injection, kind => file_eval_ex, target => {'Elixir.Code', eval_quoted, 3}, argindex => all, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Code':eval_quoted/3 usage."},
     #{desc_type => funapp, type => dos, kind => atom_exhaustion_ex, target => {'Elixir.String', to_atom, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.String':to_atom/1 usage."},
     #{desc_type => funapp, type => dos, kind => atom_exhaustion_ex, target => {'Elixir.List', to_atom, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.List':to_atom/1 usage."},
     #{desc_type => funapp, type => dos, kind => atom_exhaustion_ex, target => {'Elixir.Module', concat, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Module':concat/1 usage."},
     #{desc_type => funapp, type => dos, kind => atom_exhaustion_ex, target => {'Elixir.Module', concat, 2}, argindex => all, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Module':concat/1 usage."},
     #{desc_type => funapp, type => dos, kind => atom_exhaustion_ex, target => {'Elixir.Plug.Crypto', non_executable_binary_to_term, 1}, argindex => 1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Plug.Crypto':non_executable_binary_to_term/1 usage."},
     #{desc_type => funapp, type => dos, kind => atom_exhaustion_ex, target => {'Elixir.Plug.Crypto', non_executable_binary_to_term, 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun safe_option/1, desc => "Unsafe 'Elixir.Plug.Crypto':non_executable_binary_to_term/2 usage."}
    ]

    ++

    [
     #{desc_type => funapp, type => xss, kind => phoenix_row, target => {'Elixir.Phoenix.HTML', raw, 1}, argindex => 1, sanitiser => fun dpgettext_usage/1, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Phoenix.HTML':raw/1 usage."},
     #{desc_type => funapp, type => xss, kind => phoenix_html, target => {'Elixir.Phoenix.Controller', html, 2}, argindex => 2, ?TAINTEDCHECKERS, desc => "Unsafe 'Elixir.Phoenix.Controller':html/2 usage."},
     #{desc_type => funapp, type => xss, kind => phoenix_send_resp, target => {'Elixir.Plug.Conn', send_resp, 3}, argindex => 3, ?TAINTEDCHECKERS, sanitiser => fun first_arg_vulnerable/1, desc => "Unsafe 'Elixir.Plug.Conn':send_resp/3 usage."},

     #{desc_type => funapp, type => rce, kind => binary_rce_ex, target => {erlang, binary_to_term, 1}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun enum_usage/1, desc => "Unsafe evaluation of the data originated from an external binary."},
     #{desc_type => funapp, type => rce, kind => binary_rce_ex, target => {erlang, binary_to_term, 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun enum_usage/1, desc => "Unsafe evaluation of the data originated from an external binary."},
   
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', query, 1}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', query, 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', query, 3}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', query, 4}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', 'query!', 1}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', 'query!', 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', 'query!', 3}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', 'query!', 4}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},

     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', query_many, 1}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', query_many, 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', query_many, 3}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1,desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', query_many, 4}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', 'query_many!', 1}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', 'query_many!', 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', 'query_many!', 3}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', 'query_many!', 4}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},

     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', stream, 1}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', stream, 2}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', stream, 3}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {'Elixir.Ecto.Adapters.SQL', stream, 4}, argindex => 1, ?TAINTEDCHECKERS, sanitiser => fun is_generated/1, desc => "Unsafe SQL query."},
   
     #{desc_type => funapp, type => csp, kind => csp_policy, target => [{'Elixir.Phoenix.Controller', put_secure_browser_headers, 2},{'Elixir.PlugContentSecurityPolicy', call, 2}], argindex => 2, tainted_app_arg => [fun empty_check/1], desc => "Has default policy"},
     #{desc_type => funapp, type => csp, kind => csp_pipeline, target => {'Elixir.Phoenix.Controller', accepts, 2}, argindex => 2, sanitiser => fun csp_protected/1, tainted_app_arg => [], desc => "Missing CSP protection."},
     #{desc_type => funapp, type => csrf, kind => csrf_plug, target => {'Elixir.Plug.Conn', fetch_session}, argindex => 1,sanitiser => fun has_csrf_plug/1,tainted_app_arg => [], desc => "Missing CSRF."},
     #{desc_type => expr_pair, type => csrf, kind => csrf_action, target => {'__match_route__', 3}, sanitiser => fun action_reuse/1, desc => "CSRF Action reuse."},
     
     #{desc_type => funapp, type => session, kind => session_hijacking, target => {'Elixir.Plug.Conn', put_resp_cookie}, argindex => 4, sanitiser => fun http_only/1, tainted_app_arg => [], desc => "Vulnerable to session hijacking"},
     #{desc_type => funapp, type => session, kind => session_fixation, target => {'Elixir.Plug.Conn', configure_session}, argindex => 2, sanitiser => fun renew/1, tainted_app_arg => [], desc => "Vulnerable to session fixation"},
     #{desc_type => funapp, type => session, kind => session_leakage, target => {'Elixir.Plug.Session', call, 2}, argindex => 2, sanitiser => fun encryption_salt/1, tainted_app_arg => [], desc => "Vulnerable to session information leakage"},
     #{desc_type => funapp, type => session, kind => session_leakage, target => {'Elixir.Plug.Conn', put_resp_cookie}, argindex => 4, sanitiser => fun encrypt/1, tainted_app_arg => [], desc => "Vulnerable to session information leakage"},
  
     #{desc_type => endpoint_config, type => tls, kind => downgrade_attack, key => force_ssl, option => {hsts, false}, config_sanitiser => fun has_option/1, desc => "Vulnerable to downgrade attack"},
     #{desc_type => endpoint_config, type => tls, kind => weak_tls_verison, key => https, option => {versions, ['tlsv1.1', tlsv1]}, config_sanitiser => fun has_option/1, desc => "If using latest OTP has weak TLS version"},
     #{desc_type => endpoint_config, type => tls, kind => weak_tls_cipher, key => https, option => {cipher_suite, strong}, config_sanitiser => fun has_option/1, desc => "If using latest OTP has weak TLS cipher"},
     #{desc_type => combined, type => tls, kind => missconfigured_tls_offload, dependencies => [
        #{desc_type => funapp, target => [{'Elixir.Plug.SSL', init, 1}, {'Elixir.Plug.RewriteOn', init, 1}], argindex => 1, sanitiser => fun rewrite_on/1, tainted_app_arg => []},
        #{desc_type => endpoint_config, key => force_ssl, option => {rewrite_on, x_forwarded_proto}, config_sanitiser => fun has_option/1}
        ], desc => "Misconfigured tls offload"},
     #{desc_type => combined, type => information_leakage, kind => parameter_filter, dependencies => [
        #{desc_type => app_config, key => filter_parameters, option => ["password", "secret", "token", "passwrd", "pw"], config_sanitiser => fun app_has_option/1},
        #{desc_type => app_config, key => filter_parameters, subkey => keep, option => ["password", "secret", "token", "passwrd", "pw"], config_sanitiser => fun app_has_option/1}
     ], desc => "Vulnerable to sensitive data logging resulting with data leakage by Phoenix."}
    ]
    ++ ?DEPRECATEDS
).

-define(OLDCRYPTOFUNS, [{block_encrypt, 3}, {block_encrypt, 4}, {block_decrypt, 3}, {block_decrypt, 4},
                        {stream_init, 2}, {stream_init, 3}, {stream_encrypt, 2}, {stream_decrypt, 2},
                        {next_iv, 2}, {next_iv, 3}, {supports, 0},
                        {cmac, 3}, {cmac, 4}, {hmac, 3}, {hmac, 4}, {hmac_init, 2}, {hmac_update, 2},
                        {hmac_final, 1}, {hmac_final_n, 2}, {poly1305, 2}]).
-define(DEPRECATEDCRYPTOFUNS, [{private_decrypt, 4}, {private_encrypt, 4}, {public_decrypt, 4}, {public_encrypt, 4}]).
-define(UNSAFECRYPTOFUNS, [{sign, 4}, {sign, 5}, {verify, 5}, {verify, 6}]).

%-define(KNOWNFUNS, []).

-define(KNOWNFUNS, ?ERLANG_FUNS ++ ?ELIXIR_FUNS ++ ?PHOENIX_FUNS).

-define(ERLANG_FUNS,[{erlang, integer_to_list, 1},{lists, seq, 2},{rand, uniform, 1},{erlang, error, 1},{erlang, round, 1},
    {elixir_erl_pass,no_parens_remote,2}]).

-define(ELIXIR_FUNS,[{'Elixir.String.Chars', to_string, 1},{'Elixir.Range', new, 2}, {'Elixir.Enum', random, 1},
    {'Elixir.Function', identity, 1},{'Elixir.Float', round, 1},{'Elixir.Float', round, 2},{'Elixir.Access', get, 2}, 
    {'Elixir.Access', get, 3},{'Elixir.Enum',map_join,2}, {'Elixir.Enum',group_by,2}, {'Elixir.Enum',join,2},
    {'Elixir.Enum',reject,2},{'Elixir.String',replace,3}, {'Elixir.String',replace,4},{'Elixir.String.Chars',to_string,1}]).

-define(PHOENIX_FUNS,[{'Elixir.Gettext', dpgettext, 5}, {'Elixir.Phoenix.Component',assign,3},{'Elixir.Phoenix.LiveView.LiveStream',mark_consumable,1}]).

-define(ITERATORS, [{'Elixir.Enum',map,2}, {'Elixir.Enum',each,2},
    {lists, map, 2}, {lists, foreach, 2}, {lists, foldl, 3}, {lists, foldr, 3},
    {lists, filter, 2}, {lists, filtermap, 2}, {lists, mapfoldl, 3}, {lists, mapfoldr, 3}, {lists, flatmap, 2}]).

-define(DYN_ECTO_VULNERABILITIES(MOD),
    [#{desc_type => funapp, type => injection, kind => sql, target => {MOD, query, 1}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, query, 2}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, query, 3}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, query, 4}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, 'query!', 1}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, 'query!', 2}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, 'query!', 3}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, 'query!', 4}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},

     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, query_many, 1}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, query_many, 2}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, query_many, 3}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, query_many, 4}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, 'query_many!', 1}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, 'query_many!', 2}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, 'query_many!', 3}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, 'query_many!', 4}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},

     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, stream, 1}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, stream, 2}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, stream, 3}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."},
     #{desc_type => funapp, type => injection, kind => sql, target => {MOD, stream, 4}, argindex => 1, sanitiser => fun is_generated/1,?TAINTEDCHECKERS, desc => "Unsafe SQL query."}]
     ).