Skip to content

[Feature Request]: Separate protected-brand domains from the URL allowlist (allowlist should not seed squatting protection) #163

Description

@MWG-Logan

Summary

The user URL allowlist is currently overloaded to mean two different things at once:

  1. "Trust these exact hosts" (exclude them from scanning), and
  2. "Protect these brands from squatting" (treat them as protected domains to match lookalikes against).

These are separate concerns and should not share one list. Conflating them produces a surprising and security-relevant result: allowlisting a domain can make the customer's own legitimate lookalike host trip the squatting detector, which is the opposite of what an admin expects from a "whitelist."

This issue proposes separating the control into a dedicated protected-brands configuration option, distinct from urlAllowlist, and is intended to be implemented on its own branch later. It is filed for tracking and design, not for immediate merge.

Current behavior (evidence)

In scripts/modules/domain-squatting-detector.js:

  • initialize() extracts domains from the URL allowlist and merges them into protectedDomains:
const allowlistDomains = this.extractDomainsFromAllowlist(urlAllowlist);
if (allowlistDomains.length > 0) {
  this.protectedDomains = [...new Set([...this.protectedDomains, ...allowlistDomains])];
}
  • checkDomain() only skips an exact base-domain self-match, then scores the visited host against every other protected domain:
for (const protectedDomain of this.protectedDomains) {
  const protectedBase = this.extractBaseDomain(protectedDomain);
  if (testBase === protectedBase) { continue; } // only exact self-match skipped
  // ... levenshtein / homoglyph / typosquat / combosquat vs every OTHER brand
}

Because the skip is per-protected-domain (a continue), not a global allowlist gate, a host that is explicitly on the allowlist is still scored against other seeded brands.

Worked example (from a real report)

Allowlist contained, among others:

  • salesforce.com
  • https://client.my.salesforce.com/
  • https://client.my.salesforce-setup.com/
  • client.my.salesforce-setup.com

Visited host client.my.salesforce-setup.com (base token salesforce-setup) was still flagged as a combosquat of salesforce.com (base token salesforce), even though that exact host was on the allowlist twice. The allowlist entry for salesforce.com is precisely what seeded salesforce as a brand to match against.

Contributing facts that make this worse

  • rules/detection-rules.json ships "protected_domains": [] (empty), so the URL allowlist seeding is currently the only functional source of protected brands.
  • initialize() does not read runtimeConfig.domainSquatting.protectedDomains (camelCase, from managed schema / CIPP), so admin-supplied brands are dropped at init.
  • updateConfig(), which would read protectedDomains, is dead code and is never called.

Net effect: there is no clean, dedicated way for an admin to declare protected brands today, and the only path that works has the harmful side effect described above.

Proposed direction (future work, separate branch)

  1. Introduce a dedicated protected-brands configuration option (for example domainSquatting.protectedDomains), surfaced in the managed schema / CIPP and the options UI, that is completely separate from urlAllowlist.
  2. Stop seeding the URL allowlist into protectedDomains. The allowlist should be a pure trust list.
  3. Add a global allowlist short-circuit at the top of checkDomain() that returns null when the visited host is on the user allowlist. Match on exact host plus subdomains only (do not use the loose base-domain token compare), so that close typosquats of a trusted brand are still detected.
  4. Wire the dedicated brand config through initialize() (and retire or fix the dead updateConfig() path) so brands from rules and managed policy are honored.

Acceptance criteria

  • Allowlisting a host excludes that host and its subdomains from squatting detection entirely.
  • Allowlisting a host does not implicitly turn its brand into a protected domain.
  • Protected brands are configured through their own option, independent of the allowlist.
  • Close typosquats of a trusted brand are still detected (the exclusion is exact-host plus subdomain, not base-token).

Notes

Deferred by design. This will be implemented on a separate branch. Related shipped fixes: the log action handling (#161) and the deep-link allowlist matching in urlPatternToRegex (#162).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions