skip to Main Content

I am using the JavaScript FileReader to upload files in my web application. I want to restrict the accepted file types to only .pem and .key. However, I noticed that I am able to upload .crt and .cer files as well. Is there something wrong with my implementation? I am using the following code:

<input
  type="file"
  accept=".key, .pem"
/>

2

Answers


  1. The accept attribute doesn’t work in the way it seems you expect it to. Here’s a relevant excerpt from MDN’s documentation:

    The accept attribute doesn’t validate the types of the selected files; it provides hints for browsers to guide users towards selecting the correct file types. It is still possible (in most cases) for users to toggle an option in the file chooser that makes it possible to override this and select any file they wish, and then choose incorrect file types.

    Because of this, you should make sure that expected requirement is validated server-side.

    Login or Signup to reply.
  2. The other answer is right that you shouldn’t rely on the accept attribute to safely filter the file’s types, but one might note that this is actually a Chrome Bug (probably macOS specific).
    According to the specs, if the token in the list of comma separated tokens is

    A string whose first character is a U+002E FULL STOP character (.).
    [It i]ndicates that files with the specified file extension are accepted.

    However it seems that Chrome does look at the OS registry instead, and thus if on your OS .pem files are registered along with .cer files, they’ll both be accepted even if you did only set accept=".pem".

    This is the case on my macOS system where an lsregister -dump gives

    type id:                    public.x509-certificate (0xc634)
    bundle:                     CoreTypes (0x1d34)
    uti:                        public.x509-certificate
    localizedDescription:       "ar" = "شهادة (X.509)", "ca" = "certificat (X.509)", "cs" = "certifikát (X.509)", "da" = "certifikat (X.509)", "de" = "Zertifikat (X.509)", "el" = "πιστοποιητικό (X.509)", "en" = "certificate (X.509)", "en_AU" = "certificate (X.509)", "en_GB" = "certificate (X.509)", "es" = "certificado (X.509)", "es_419" = "certificado (X.509)", "fi" = "varmenne (X.509)", "fr" = "certificat (X.509)", "fr_CA" = "certificat (X.509)", "he" = "אישור (X.509)", "hi" = "सर्टिफ़िकेट (X.509)", "hr" = "certifikat (X.509)", "hu" = "tanúsítvány (X.509)", "id" = "sertifikat (X.509)", "it" = "certificato (X.509)", "ja" = "証明書(X.509)", "ko" = "인증서(X.509)", "LSDefaultLocalizedValue" = "certificate (X.509)", "ms" = "sijil (X.509)", "nl" = "certificaat (X.509)", "no" = "sertifikat (X.509)", "pl" = "certyfikat (X.509)", "pt_BR" = "certificado (X.509)", "pt_PT" = "certificado (X.509)", "ro" = "certificat (X.509)", "ru" = "сертификат (X.509)", "sk" = "certifikát (X.509)", "sv" = "certifikat (X.509)", "th" = "ใบรับรอง (X.509)", "tr" = "sertifika (X.509)", "uk" = "сертифікат (X.509)", "vi" = "chứng nhận (X.509)", "zh_CN" = "证书(X.509)", "zh_HK" = "證書(X.509)", "zh_TW" = "憑證(X.509)"
    flags:                      active  public  apple-internal  exported  core  trusted (0000000000000077)
    conforms to:                public.data
    tags:                       .cer, .der, .crt, .pem, application/x-x509-ca-cert
    

    As you can see, all these extensions share the same type id, and thus in my Chrome they’re all equivalent. This is not the case e.g. in Firefox, which does respect the specs and really filter by extension.

    (Note: I don’t think I’ve got anything that affected these extensions.)

    Unfortunately there isn’t much you can do about it, since using the MIME type (application/x-x509-ca-cert) would have the exact same result. The best would be to star the linked issue and hope they can fix it some day.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search