diff --git a/apps/emqx_auth/src/emqx_authn/emqx_authn_utils.erl b/apps/emqx_auth/src/emqx_authn/emqx_authn_utils.erl index fb6bf98fa..13f8f238b 100644 --- a/apps/emqx_auth/src/emqx_authn/emqx_authn_utils.erl +++ b/apps/emqx_auth/src/emqx_authn/emqx_authn_utils.erl @@ -207,10 +207,20 @@ is_superuser(#{}) -> #{is_superuser => false}. client_attrs(#{<<"client_attrs">> := Attrs}) -> - #{client_attrs => Attrs}; + #{client_attrs => drop_invalid_attr(Attrs)}; client_attrs(_) -> #{client_attrs => #{}}. +drop_invalid_attr(Map) when is_map(Map) -> + maps:from_list(do_drop_invalid_attr(maps:to_list(Map))). + +do_drop_invalid_attr(KVL) -> + F = fun({K, V}) -> + emqx_utils:is_restricted_str(K) andalso + emqx_utils:is_restricted_str(V) + end, + lists:filter(F, KVL). + ensure_apps_started(bcrypt) -> {ok, _} = application:ensure_all_started(bcrypt), ok; diff --git a/apps/emqx_auth_http/test/emqx_authn_http_SUITE.erl b/apps/emqx_auth_http/test/emqx_authn_http_SUITE.erl index 576a22203..7b2aae9f1 100644 --- a/apps/emqx_auth_http/test/emqx_authn_http_SUITE.erl +++ b/apps/emqx_auth_http/test/emqx_authn_http_SUITE.erl @@ -542,13 +542,21 @@ samples() -> Req = cowboy_req:reply( 200, #{<<"content-type">> => <<"application/json">>}, - emqx_utils_json:encode(#{result => allow, is_superuser => true}), + emqx_utils_json:encode(#{ + result => allow, + is_superuser => true, + client_attrs => #{ + fid => <<"n11">>, + <<"_bad_key">> => <<"v">>, + <<"ok_key">> => <<"but bad value">> + } + }), Req0 ), {ok, Req, State} end, config_params => #{}, - result => {ok, #{is_superuser => true, client_attrs => #{}}} + result => {ok, #{is_superuser => true, client_attrs => #{<<"fid">> => <<"n11">>}}} }, %% get request with url-form-encoded body response diff --git a/apps/emqx_utils/src/emqx_utils.erl b/apps/emqx_utils/src/emqx_utils.erl index 12855b9b6..007c2b54b 100644 --- a/apps/emqx_utils/src/emqx_utils.erl +++ b/apps/emqx_utils/src/emqx_utils.erl @@ -67,7 +67,8 @@ format/1, call_first_defined/1, ntoa/1, - foldl_while/3 + foldl_while/3, + is_restricted_str/1 ]). -export([ @@ -861,6 +862,13 @@ ntoa({0, 0, 0, 0, 0, 16#ffff, AB, CD}) -> ntoa(IP) -> inet_parse:ntoa(IP). +%% @doc Return true if the provided string is a restricted string: +%% Start with a letter or a digit, +%% remaining characters can be '-' or '_' in addition to letters and digits +is_restricted_str(String) -> + RE = <<"^[A-Za-z0-9]+[A-Za-z0-9-_]*$">>, + match =:= re:run(String, RE, [{capture, none}]). + -ifdef(TEST). -include_lib("eunit/include/eunit.hrl").