Skip to content

v1.3.0

Choose a tag to compare

@daniesy daniesy released this 31 Jul 01:43
· 9 commits to master since this release

v1.3.0 — Teach users what they missed

Until now, a user who fell for a simulated phishing page was redirected straight to the oops page. They learned that they failed, but not what they should have noticed. This release adds an interactive tutorial that inspects the page they fell for, walks them through the warning signs they missed, and then performs the same redirect.

It is off by default. Existing integrations behave exactly as before.

const ev = new ATSEvents({
  apiKey: "YOUR_API_KEY",
  tutorial: true,
});
ev.listen();

What the tutorial explains

The page is scanned the moment the event fires, and every dangerous item found becomes its own step with the element highlighted in place.

  • The address — not a generic warning, but why this URL should have raised suspicion: a raw IP, a lookalike built from special characters, a brand parked in a subdomain, a throwaway TLD, or an address long enough to push the real name out of sight. The part that decides ownership is highlighted, and the readout keeps the deceptive bits other tools hide, such as the user@host trick and non-default ports.
  • Credential and card forms — recognised from labels, ARIA text and surrounding copy, so forms with no <form> element and password fields typed as text are still caught.
  • Downloads — links and buttons that would have delivered a file.
  • Links that lie — where the visible text and the real destination differ.
  • Pressure tactics — the deadline or account-suspension threat is quoted back to the user in their own language.
  • Brand impersonation — when a page presents itself as an organisation the address does not belong to.
  • Permissions — microphone, camera, location, notifications, clipboard and browser extensions each get their own explanation of what was just granted.

Brand detection without a list

Rather than shipping a list that would always be out of date, the tutorial works out which organisation a page claims to be by scoring independent signals — the copyright line, og:site_name, logo alt text and file names, inline SVG wordmarks, the title and headings — and only names a brand once they agree. That works for organisations nobody bundled a list for, in any language.
If your campaign already knows what the landing page imitates, send it as ats_brand in the campaign token and that value is used instead of any guess.

Languages

Ten locales, each reviewed by a native speaker: en-US, ro-RO, es-ES, ca-ES, es-419 (also accepted as es-LATAM), pt-BR, pt-PT, fr-FR, de-DE, el-GR. The language comes from the locale option, then the campaign token, then the browser, falling back to en-US.

New options

Option Type Default Description
tutorial boolean false Show the tutorial instead of redirecting immediately
tutorialSkippable boolean true Show a skip link
locale string auto Force the tutorial language

Smaller bundle

Source maps were being inlined as base64 into the shipped file, where they accounted for three quarters of every byte. They are now emitted as separate .map files, which browsers only fetch when devtools are open.

Before After
bundle.min.js 244 KB 190 KB
gzipped ~73 KB 61 KB

The bundle is smaller than the previous release despite carrying the whole feature.

Reliability

The redirect is the one thing that must never be lost, so it is now guaranteed on every path. A throwing event subscriber, a failed page scan, or an overlay that the host page hides or removes all fall back to navigating. Since landing pages are attacker-authored, the overlay is checked after opening and the redirect happens anyway if it is not genuinely on screen.

Toolchain

Dependencies were updated: ESLint 10 (flat config), TypeScript 6,
@typescript-eslint 8, webpack-cli 7 and ua-parser-js 2.

Contributors should note that TypeScript stays on 6.x. TypeScript 7 is the Go rewrite and exposes a different JS API, which ts-loader cannot drive; moving to it would mean switching to a different loader.

There are no API changes for consumers of the package.