Bots have found 3 of my low traffic sites and are continually posting to pages including

alt text

I didn’t mind until my email transport provider Postmark blocked me due to spam compaints. The requests are all queued now as as shown above

Image above shows a new user registering at 01:08:43

alt text

Headless chrome from which according to is:

    "query": "",
    "continent": "Europe",
    "country": "France",
    "city": "Strasbourg",
    "org": "Host Europe GmbH",
    "as": "AS21499 Host Europe GmbH",
    "asname": "GODADDY-SXB",
    "mobile": false,
    "proxy": true,
    "hosting": false

So a Godaddy server doing Headless Chrome requests to my server. Not a real user!

However I believe the email is a real email (which was scraped from an American site). This type of action is the cause of my spam compaints.

Lets try some strategies

1. Honeypot hidden field

Just an extra html input box which is hidden via css. It will be blank for a human, but a bot will probably try to fill it in.

<div class="hidden">
    <input asp-for="Email2" class="input-text" value="">


.hidden {
    display: none;

and some backend code:

if (Email2 == null)
    Log.Information("honeypot field not filled out - good!");
    Log.Warning("honeypot field has something in it - possible bot");
    ModelState.AddModelError("Password", "Are you a human?");

alt text

It did stop some requests like this one. You can see that my ‘hidden’ field called Email2

But not the HeadlessChrome above…


Completely Automated Public Turing test to tell Computers and Humans Apart

I’ve now got rid of 99% of the junk that way coming in.

alt text

Some simple maths - yes lets see how long it takes for him to break this.

3. Form Token

ValidateAntiForgeryToken should have worked below. Maybe the ones I saw had found a clever way around it.


Simple things to check!

Check POST methods on pages

I’d forgotton to remove an OnPost method on a test contact page - so lets close that loophole! And log whats happening to see if the trap has worked.

 public class ContactModel : PageModel
     public async Task<IActionResult> OnPost(string? email, string? message)
         // was getting lots of spam posted to this unused method so lets log it
         // to make sure we're getting all of it
         Log.Warning($"email is {email}");
         Log.Warning($"message is {message}");
         return LocalRedirect("/email-fail");

         // email sending stuff here that was getting hit

Newsletter Sign up / Contact Us form

alt text I don’t get any interest from this form, so simplify by ditching out the Send, and leave my email on it.


Fixing POST methods I’d left open, having a honeypot field and a simple CAPTCHA has worked!

Postmark have excellent support (thanks Abdullah) and turned back on my email sending very quickly.

Next steps will be to make more complex CAPTCHA’s (but lets face it, an AI call could break most of that)..

Then after that look at Google’s reCAPTCHA

+24 Hours - 1 person got through

1 person has got past my What is 2 + 1 captcha. I sent ‘them’ an email which came from a residential IP address from Pakistan with what looks like a reasonable UserAgent ie it wasn’t HeadlessChrome. Nothing heard back so far.

So lets try a more complex captcha!

What is the capital city of Scotland :-)

2 Days

No bad actors have got through

3 Weeks

I’ve had 4 people get through who are not ‘real’. One person tried ‘Edimburg’ and also ‘Dublin’ but got the right answer on the 3rd attempt.

I’ve had 1 person who is real.

I send an email back to ask if they want any more information or would like a demo.

Appendix - pay people to break captcha’s.