Ich würde das mit einer `clist` machen.  Testet auch auf Leerzeichen und nutzt das `l3msg`-Interface für Warnungen.
    \documentclass{article}
    \usepackage{xparse}
    
    \ExplSyntaxOn
    
    \clist_new:N \l_allowed_chars_clist
    \clist_set:Nn \l_allowed_chars_clist { 0, 1, a, b }
    
    \msg_new:nnn { noname } { erroneous-input } { Erroneous~character~`#1' }
    
    \cs_new_protected:Npn \test_mit_tl:n #1
     {
      % Check for spaces
      \seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 }
      \int_compare:nT { \seq_count:N \l_tmpa_seq > 1 }
       { \msg_warning:nnn { noname } { erroneous-input } { ~ } }
    
      % Check for invalid tokens
      \seq_set_split:Nnn \l_tmpa_seq { } { #1 }
      \tl_map_inline:nn { #1 }
       {
        \clist_if_in:NnF \l_allowed_chars_clist { ##1 }
         { \msg_warning:nnn { noname } { erroneous-input } { ##1 } }
       }
     }
    
    \NewDocumentCommand \Befehl {m}
     {
      \test_mit_tl:n {#1}
     }
    
    \ExplSyntaxOff
    
    \begin{document}
    \Befehl{12 ab}
    \end{document}