Honeypot does not filter bots

657 Views Asked by At

I've been getting blasted with spam from the forms on my website. So I set up honeypots on both forms, but only one seems to be working. In the spam submissions I'm getting post honeypot, the honeypot fields are all filled out...

It's a static site (stores information in yaml files). The forms use Formspree.

Here's the JavaScript that that handles the forms - the honeypot code is in the submit function:

window.addEventListener("DOMContentLoaded", function() {
  // get the form elements defined in your form HTML above
  
  var forms = document.getElementsByClassName("contact-form");
  
  Array.from(forms).forEach(function(form) {
    var status = $(form).find(".contact-form-status")[0];
    
    // Success and Error functions for after the form is submitted
    
    function success() {
      form.reset();
      status.innerHTML = "Thanks!";
    }
    
    function error() {
      status.innerHTML = "Fill out all fields!";
    }
    
    // handle the form submission event
    
    form.addEventListener("submit", function(ev) {
      ev.preventDefault();
      var data  = new FormData(form),
          honey = $(form).find('.honey'),
          bot   = false;
      // weed out the bots
      honey.each(function() {
        var input = $(this),
            type  = input.attr('type');
        
        if ('checkbox' === type) {
          if (input.is(':checked')) {
            bot = true;
          }
        }
        if ('text' === type || 'email' === type) {
          if (input.val() !== '') {
            bot = true;
          }
        }
      });
      
      if (bot) { return false; } // exit function upon finding a bot
      ajax(form.method, form.action, data, success, error);
    });
    
  });
  
  // helper function for sending an AJAX request
  
  function ajax(method, url, data, success, error) {
    var xhr = new XMLHttpRequest();
    xhr.open(method, url);
    xhr.setRequestHeader("Accept", "application/json");
    xhr.onreadystatechange = function() {
      if (xhr.readyState !== XMLHttpRequest.DONE) return;
      if (xhr.status === 200) {
        success(xhr.response, xhr.responseType);
      } else {
        error(xhr.status, xhr.response, xhr.responseType);
      }
    };
    xhr.send(data);
  }
});

And here's the form in question:

<form id="contact-form"
      class="contact-form"
      action="https://formspree.io/f/xqkgpllv"
      method="POST">
  <input type="email" name="email" class="input" placeholder="email" onfocus="this.placeholder = ''" onblur="this.placeholder = 'email'" validate="email">
  <input type="hidden" name="message" value="sign me up for emails">
  <input type="checkbox" name="contact_me_by_fax_only" value="1" tabindex="-1" autocomplete="off" class="honey">
  <input type="text" name="name_2" tabindex="-1" autocomplete="off" class="honey input">
  <input type="email" name="email_2" tabindex="-1" autocomplete="off" class="honey input">
  <textarea type="text" name="message_2" tabindex="-1" autocomplete="off" class="honey input"></textarea>
  <input type="checkbox" name="contact_me_by_fax_only" value="1" autocomplete="off" class="honey input">
  <button type="submit" class="contact-form-button btn" value="-_-"></button>
  <p class="contact-form-status"></p>
</form>

It has a million honeypots because I REALLY wanted this to work.

And the CSS for the honeypot fields:

input.honey {
  position: fixed;
  left: -100px;
  bottom: 100px;
  pointer-events: none;
  background-color: transparent !important;
  color: transparent !important;
  border: none !important;
  box-shadow: none !important;
  appearance: none;
  -webkit-appearance: none;
  resize: none;
}

I avoided using display: none or visibility: hidden or opacity: 0 because I heard bots can pick that out.

If anything jumps out at you as wrong or suspicious, let me know!

1

There are 1 best solutions below

0
Patryk Chowratowicz 'Zszywacz' On

You should validate form at https://formspree.io/f/xqkgpllv with backend code, not with js preventing event. I could simply disable your JS on my client-side.