Challenging automation flows

While automation tools are fundamental to modern software development, they also have the innate potential to be used for malicious purposes. This applies to Puppeteer and Playwright, too.

As a consequence, some user flows are made purposely hard to automate to defend against threat actors. Some examples:

  1. New user signup
  2. Social login through providers like Google, Facebook etc.
  3. “Forgot password” and similar reset scenarios

There are several means through which automation is made more difficult.

Captchas

It is beyond the point of a test to try and solve a captcha: we are not trying to verify that the captcha itself works, rather to get past the captcha so we can test the functionality of our target platform. Also, if we were able to automatically solve a captcha, that would defeat the whole purpose of including one in our application.

For pre-production environments, we can:

  1. Set captcha to always pass
  2. Have captchas removed

Bot detection

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 
(KHTML, like Gecko) HeadlessChrome/79.0.3945.0 Safari 537.36

Bot detection could be deactivated for pre-production environments in order to allow automation. For production environments, a secret may be included in the User-Agent (or similar mechanism) for the system to recognise test bots and allow them through:

With Puppeteer :

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setUserAgent('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/79.0.3945.0 Safari 537.36 Secret/<MY_SECRET>');

With Playwright:

const browser = await chromium.launch();
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/79.0.3945.0 Safari 537.36 Secret/<MY_SECRET>'
});
const page = await context.newPage('https://example.com');

Automation-resistant UIs

In these cases, UI automation is specifically made more difficult by utilising components that are harder to interact with, and in some cases by randomising attribute values for key elements in order to prevent referencing. Even if this measure does not defeat all attempts, it can make it excruciatingly hard to produce reliable automated scripts, which might be enough to discourage a large number of attackers.

Warning:
Whenever looking at production environments, keep in mind that adding exceptions to any of the methods listed above might open new attack vectors for malicious users. Always conduct proper risk analysis before proceeding.

Further reading

Banner image: “Rusty Machine” by darkday. is licensed under CC BY 2.0

Head of Developer Relations @ Checkly, core theheadless.dev contributor.