Some tags in the output from my controller are filtered away I have a controller defined in MODULE.routing.yml which returns:

return array(
      '#type' =&gt; 'markup',
      '#markup' =&gt; $this-&gt;content(),
      '#attached' =&gt; array(
        'library' =&gt; $libs,
      ),
    );


The content contains H2, INPUT and SELECT (amongst others). The INPUT and SELECT are removed so I guess there's an input filter being run on this markup. 

How do I control the input filter for this controller and/or disable it completely?
That is behavior Drupal 8 has for the #markup property, as described in Render API overview. It is different from the behavior Drupal 7 had; if you are converting code from Drupal 7, you need to change that part of the code accordingly.


  #markup: Specifies that the array provides HTML markup directly. Unless the markup is very simple, such as an explanation in a paragraph tag, it is normally preferable to use #theme or #type instead, so that the theme can customize the markup. Note that the value is passed through \Drupal\Component\Utility\Xss::filterAdmin(), which strips known XSS vectors while allowing a permissive list of HTML tags that are not XSS vectors. (I.e, &lt;script&gt; and &lt;style&gt; are not allowed.) See \Drupal\Component\Utility\Xss::$adminTags for the list of tags that will be allowed. If your markup needs any of the tags that are not in this whitelist, then you can implement a theme hook and template file and/or an asset library. Aternatively, you can use the render array key #allowed_tags to alter which tags are filtered.


The highlighted part tells you how to solve the filtering of tags.

See also the next part of the documentation.


  #allowed_tags: If #markup is supplied this can be used to change which tags are using to filter the markup. The value should be an array of tags that Xss::filter() would accept. If #plain_text is set this value is ignored.