Skip to content

4 · Applications & URL regex

An Application answers "which requests does this policy apply to?" It's built almost entirely from one HAR field — request.url — plus optionally request.method. A Rule won't run unless its Application matches the request, so getting this right (precise, but not brittle) matters.


Anatomy of an Application

Field From HAR Notes
Name Unique, human-readable. e.g. Contact List HubSpot
Definition(s) request.url One or more URL match rules (below)
Method request.method Restrict to GET/POST/… or leave empty for all
Content Type request.postData.mimeType / response content.mimeType Optionally restrict
Behavior Match (apply policy) or Bypass (exempt)

An Application can be reused across many Rules. For example, a single broad Salesforce GraphQL Application (acme.my.salesforce.com/services/data/v59.0/graphql) can be shared by many GraphQL operations — because GraphQL sends everything to one URL, the operation is distinguished in the Data Type, not the Application.


Definition types (URL match)

Each definition targets a part of the URL. Pick the most specific type that isn't brittle:

Type Matches Example
Domain Domain and all subdomains salesforce.comacme.my.salesforce.com, na1.salesforce.com
Hostname A specific host (supports * wildcard) acme.my.salesforce.com, *.hubapi.com
Path URL path prefix /crm/v3/objects/contacts
Object Part Any single path segment (substring of the path) contacts
Query String Substring of the query string limit=
Full URL Substring of the entire URL acme.my.salesforce.com/services/apexrest/discount
Regex Regular expression against the full URL api\.hubapi\.com\/crm\/v3\/objects\/contacts\?.*

Most custom policies use either Full URL (simple, readable) or Regex (when you need to pin a path and a query parameter, or allow variation).

Regex matches the whole URL string

A Regex definition is tested against the complete URL (scheme + host + path + query). It's a contains-style test unless you anchor with ^…$. Escape the dots (\.) and the ? (\?) so they're literal. RE2 syntax — no look-around.


Turning request.url into a match

  1. Copy the URL from the HAR: https://api.hubapi.com/crm/v3/objects/contacts?limit=25&archived=false
  2. Decide what's stable vs incidental:
  3. Host (api.hubapi.com) and path (/crm/v3/objects/contacts) → stable, keep them.
  4. limit=25, archived=false → values vary; match the parameter name, not the value.
  5. Write the tightest match that still catches every variant:
api\.hubapi\.com\/crm\/v3\/objects\/contacts\?.*

(A Regex definition. It pins host + path and requires a query string (the list call), but tolerates any limit / paging params.)

  1. Add the Method if the same path serves different verbs. The contact-list block is GET only, so set Method = GET to avoid touching the POST that creates a contact.

Precise but not brittle — the balance

Too loose Too tight
Domain: salesforce.com for a single endpoint → scans every Salesforce subdomain, wastes cycles, risks false hits Full URL with limit=25&archived=false hard-coded → breaks the moment paging changes

Good middle ground: pin host + path, match query parameters by name, ignore their values, and constrain the method. The Data Type does the fine-grained work inside the body; the Application just needs to get the right requests onto the conveyor belt.

GraphQL special case

GraphQL APIs send every operation to the same URL (/graphql). So:

  • The Application is broad: a Full URL match on acme.my.salesforce.com/services/data/v59.0/graphql, method POST.
  • The Data Type does the discrimination via a Condition on operationName (see Custom Data Types).

Don't try to distinguish GraphQL operations in the URL — you can't; they're all the same URL.


Bypass definitions

Behavior = Bypass creates an exemption. Use it to carve a quiet sub-path out of a broad Match — e.g. Match Domain: company.com but Bypass Hostname: blog.company.com so the public blog is never scanned. Bypass wins over Match.



Wiring it into a Rule

Once you have an Application (this chapter) and a Custom Data Type (previous chapter), the rest is standard Shield configuration that doesn't depend on the HAR:

  1. Pick a Mask Format (how the value is transformed).
  2. Create an Obfuscation pairing the Data Type with that Mask Format.
  3. Create a Rule — set the Action (Detect / Obfuscate / Block), the Apply To (Request if the data was in request.postData, Response if it was in response.content), and attach the Application + Obfuscation.

These three objects are documented in the Admin Console docs (Mask Formats · Obfuscations · Rules) and aren't re-explained here.


Next: Full worked example →