Skip to main content

Axur Credentials Feed - ServiceNow

How to create a ServiceNow incident for every exposed credential detected by the Axur Platform, using a Credentials Feed (Push or Pull).

Overview

A Credentials Feed delivers the exposed credentials (leaked logins of employees or customers) that the Axur Platform detects. A small script in ServiceNow turns each credential into an Incident record, so your team can reset the password and track the response.

Figure 1: The two delivery modes. Both use the same JSON and the same mapping script.

  • Push (Webhook 2.0): near real-time

    • The Axur Platform sends credentials to an endpoint you create in ServiceNow. Your instance must accept inbound calls.

  • Pull (polling): easier to approve

    • ServiceNow queries the feed every X minutes. Traffic is outbound only, and latency equals the schedule interval.

Already using the Tickets Feed guide?

This guide follows the same structure, with its own script names (AxurCredentialFeedMapper, axur.credentials_feed.url). Both integrations can run side by side in the same instance and can share the same API Key property.

Prerequisites

  • A ServiceNow instance and an admin user (or web_service_admin for Push). To test first, use a free Personal Developer Instance (PDI) from developer.servicenow.com. Its URL looks like https://dev123456.service-now.com.

  • A manager user on the Axur Platform to create the feed.

  • An Axur Platform API Key (Pull only). See step "Get the API Key (Pull only)".

Classic UI vs. Next Experience

ServiceNow menus look different in the classic interface (UI16) and in Next Experience (the All menu). Some shortcuts, such as typing sys_properties.list in the filter, do not work in every version. Every step below also gives a direct URL that works in both interfaces. Replace <instance> with your instance name, e.g. dev123456.

Direct URLs used in this guide

What

Direct URL

New system property

https://<instance>.service-now.com/sys_properties.do?sys_id=-1

System properties list

https://<instance>.service-now.com/sys_properties_list.do

New Script Include

https://<instance>.service-now.com/sys_script_include.do?sys_id=-1

New Scheduled Script Execution

https://<instance>.service-now.com/sysauto_script.do?sys_id=-1

New Scripted REST API

https://<instance>.service-now.com/sys_ws_definition.do?sys_id=-1

Incidents created by the feed

https://<instance>.service-now.com/incident_list.do?sysparm_query=correlation_idISNOTEMPTY

System logs

https://<instance>.service-now.com/syslog_list.do


Get the feed and API Key from the Axur Platform

Do this step first. Pull needs both the feed URL and the API Key before you create anything in ServiceNow.

Create the feed

  1. Go to one.axur.com/api-integrations → Feeds section → Add feed. You can pick the Employee credentials or User credentials template, or click Skip templates.

  2. Choose the Credentials type.

  3. Choose the delivery mode: Pull or Push. For Push, enter the endpoint URL you create in step 6.

  4. Event date is pre-filled with the creation date (created). Each credential arrives once, when the Axur Platform first detects it.

  5. Under Feed parameters, choose which credentials to receive. Combine filters with &:

  6. Recommended: also add the fields parameter shown below. The feed then returns only what the script uses, and passwords never leave the Axur Platform:

    fields=id,created,detectionDate,customer,assets,status,credential.types,user,user.type,access.url,source.name

    Example combined with a filter: credential.types=employee&fields=id,created,…

  7. Set a title, e.g. “ServiceNow – Exposed credentials”, and save.

  8. Copy the feed URL shown for the feed in the list. It looks like https://api.axur.com/gateway/1.0/api/integration-feed/feeds/feed/<ID>.

Figure 2: Suggested feed configuration (illustration; the actual screen may look different).

Get the API Key (Pull only)

  1. On the Axur Platform, open My Preferences → API KEY tab.

  2. Create a new key and copy it right away. Store it in a password manager until you create the ServiceNow property in "Store the URL and API Key".

The key belongs to the user who created it

The key only sees what that user can see on the Axur Platform. If the user is deactivated, blocked, or removed, the key is revoked and the job starts failing with 401 Unauthorized. Create the key with a user who has access to the credentials and will not be deactivated, such as a dedicated integration user. Never share the key or write it in scripts.


Field mapping

Each item in collectionData.detections[] becomes a record in the Incident table. The colors show where each piece of information comes from:

Mapping table

ServiceNow field

Source in the JSON

Notes

state

fixed 1

Set on creation only. Updates do not reopen the incident.

correlation_id

id

Used to avoid duplicates.

correlation_display

id

short_description

Data Leakage - Type - customer - user @ access.url

Capped at 160 characters: only the user/URL part is shortened (with ...).

description

Template in Figure 3b

Link: https://one.axur.com/data-leakage/credentials?customerId={customer}&text={id}

Credential type labels

credential.types

Label in the Incident

employee

Employee credential exposed

user

User credential exposed

both

Employee and User credential exposed

The password is never written to ServiceNow

The script does not copy the password into the Incident, even if the feed sends it. Incidents are visible to many people and kept for a long time, so storing exposed passwords there would create a new leak. Your team can see the full detection on the Axur Platform through the link in the description.

Watch out for dotted keys

Fields like access.url and credential.types have a dot in their name. In JavaScript, use brackets: d['access.url'], not d.access.url.


Script Include: the mapper

This script builds the fields and creates or updates the incident. You create it once, and both Push and Pull use it.

  1. Open https://<instance>.service-now.com/sys_script_include.do?sys_id=-1. From the menu, the path is System Definition › Script Includes → New.

  2. Name: AxurCredentialFeedMapper (must be exactly this name).

  3. Paste the code below into the Script field and save.

var AxurCredentialFeedMapper = {
TABLE: 'incident',
CREDENTIALS_URL: 'https://one.axur.com/data-leakage/credentials',
SHORT_DESCRIPTION_LIMIT: 160,
WORKSPACE: 'Data Leakage',

TYPE_LABELS: {
'employee': 'Employee',
'user': 'User'
},

buildFields: function (item) {
var id = item.id;
var customer = item.customer || '';
var user = item.user || '';
var accessUrl = item['access.url'] || '';
var typeLabel = this.typeLabel(item['credential.types'] || []);

var prefix = this.WORKSPACE + ' - ' + typeLabel + ' credential exposed - ' + customer + ' - ';
var target = accessUrl ? user + ' @ ' + accessUrl : user;
var shortDescription = prefix + this.fit(target, prefix.length);

var link = this.CREDENTIALS_URL + '?customerId=' + encodeURIComponent(customer)
+ '&text=' + encodeURIComponent(id);

var description = [
'Axur - one.axur.com',
'',
'New credential exposure detected (' + link + ')',
'',
'Detection ID: ' + id,
this.assetsLine(item.assets || []),
'Credential Type: ' + typeLabel,
'User: ' + user + (item['user.type'] ? ' (' + item['user.type'] + ')' : ''),
'Access URL: ' + accessUrl,
'Source: ' + (item['source.name'] || ''),
'Status: ' + (item.status || ''),
'Detection Date: ' + this.formatDate(item.detectionDate || item.created)
].join('\n');

return { id: id, shortDescription: shortDescription, description: description };
},

typeLabel: function (types) {
var labels = [];
for (var i = 0; i < types.length; i++) {
labels.push(this.TYPE_LABELS[types[i]] || types[i]);
}
return labels.length ? labels.join(' and ') : 'Unknown';
},

fit: function (text, usedLength) {
var available = this.SHORT_DESCRIPTION_LIMIT - usedLength;
if (text.length <= available) return text;
return text.substring(0, Math.max(available - 3, 0)) + '...';
},

assetsLine: function (assets) {
if (assets.length === 0) return 'Asset: -';
return assets.length === 1 ? 'Asset: ' + assets[0] : 'Assets: (' + assets.join(', ') + ')';
},

formatDate: function (iso) {
if (!iso) return '';
return iso.substring(8, 10) + '/' + iso.substring(5, 7) + '/' + iso.substring(0, 4);
},

upsert: function (item) {
var f = this.buildFields(item);
if (!f.id) return;

var gr = new GlideRecord(this.TABLE);
gr.addQuery('correlation_id', f.id);
gr.query();
var exists = gr.next();
if (!exists) {
gr.initialize();
gr.state = 1;
}
gr.correlation_id = f.id;
gr.correlation_display = f.id;
gr.short_description = f.shortDescription;
gr.description = f.description;
if (exists) { gr.update(); } else { gr.insert(); }
},

processPayload: function (payload) {
var detections = (payload && payload.collectionData && payload.collectionData.detections) || [];
for (var i = 0; i < detections.length; i++) {
this.upsert(detections[i]);
}
return detections.length;
}
};

Option A: Pull with a Scheduled Job

Pick this option if your instance cannot receive external calls.

Store the URL and API Key

Before you start: have the feed URL and the API Key at hand.

  1. Open the new property form directly: https://<instance>.service-now.com/sys_properties.do?sys_id=-1. You can also open sys_properties_list.do and click New.

  2. Create the feed URL property:

  3. If axur.feed.api_key does not exist yet (it is shared with the Tickets Feed integration), open the form again and create it:

Security

Never write the API Key directly in the script. If your security team prefers, use Connection & Credential Aliases instead of the system property.

Create the schedule

  1. Open https://<instance>.service-now.com/sysauto_script.do?sys_id=-1. From the menu, the path is System Definition › Scheduled Jobs → New → Automatically run a script of your choosing.

  2. Name: Axur Credentials Feed → Incident. Run: Periodically. Repeat interval: 00:05:00 (5 min).

  3. Paste the script below and save.

Figure 4: Scheduled Job running every 5 minutes (illustration).

var FEED_URL = gs.getProperty('axur.credentials_feed.url');
var API_KEY = gs.getProperty('axur.feed.api_key');
var MAX_PAGES = 20;

for (var page = 0; page < MAX_PAGES; page++) {
var request = new sn_ws.RESTMessageV2();
request.setEndpoint(FEED_URL);
request.setHttpMethod('GET');
request.setRequestHeader('Authorization', 'Bearer ' + API_KEY);
request.setRequestHeader('Accept', 'application/json');

var response = request.execute();
if (response.getStatusCode() != 200) {
gs.error('Axur credentials feed: HTTP ' + response.getStatusCode() + ' - ' + response.getBody());
break;
}

var processed = AxurCredentialFeedMapper.processPayload(JSON.parse(response.getBody()));
if (processed === 0 || FEED_URL.indexOf('dry-run=true') > -1) break;
}

Each call to the feed moves the pointer forward and returns the next batch. The loop runs until a batch comes back empty, capped at 20 calls per run so the job never hangs. In dry-run mode the pointer does not move, so the job makes a single call per run.


Option B: Push with a Scripted REST API

Pick this option to receive credentials in near real-time. Your instance must accept inbound calls from the Axur Platform.

  1. Open https://<instance>.service-now.com/sys_ws_definition.do?sys_id=-1. From the menu, the path is System Web Services › Scripted Web Services › Scripted REST APIs → New.

  2. Name: Axur Credentials Feed, API ID: axur_credentials_feed. Save.

  3. On the Resources tab → New: Name credentials, HTTP method POST, Relative path /credentials.

  4. Paste the script below into the resource and save.

  5. Copy the Resource path (e.g. https://<instance>.service-now.com/api/<scope>/axur_credentials_feed/credentials) and enter it as the Push feed endpoint in the Axur Platform.

(function process(request, response) {
var processed = AxurCredentialFeedMapper.processPayload(request.body.data);
response.setStatus(200);
response.setBody({ processed: processed });
})(request, response);

Endpoint authentication

The resource requires ServiceNow authentication by default (Requires authentication). Do not disable it. Instead, let the Axur Platform authenticate on every call:

  1. In ServiceNow, create a dedicated integration user (e.g. axur.integration) with only the roles needed to create and update incidents.

  2. When you configure the Push feed on the Axur Platform, add a custom header with that user's credentials: Authorization: Basic <base64 of user:password>. The Axur Platform sends your custom headers on every request.

Optional: verify the signature

Every Push request also carries an X-Push-Signature header: an HMAC-SHA256 of the raw request body, hex-encoded, computed with the secret key of the Push feed. Validate it in the resource if your security team requires proof that the call came from the Axur Platform.

Connection test

When you save or test the Push feed, the Axur Platform sends an empty body ({}). The script answers 200 with processed: 0 and creates nothing.


Test and validate

  1. Turn on dry-run temporarily: open the axur.credentials_feed.url property (sys_properties_list.do, search by name) and add ?dry-run=true to the end of its Value, e.g. https://api.axur.com/gateway/1.0/api/integration-feed/feeds/feed/<ID>?dry-run=true. Save. The feed now returns the same credentials on every call and its pointer does not move, so nothing is lost while you test.

  2. Run the job manually: open the Scheduled Job → Execute Now.

  3. Check the incidents at incident_list.do?sysparm_query=correlation_idISNOTEMPTY. Confirm that no password appears in the Incident.

  4. Run it again. Thanks to the upsert, the number of incidents should not grow.

  5. Check for errors at syslog_list.do or under System Logs › Errors (messages starting with Axur credentials feed:).

  6. All good? Edit axur.credentials_feed.url again and remove ?dry-run=true from its value, so the pointer starts moving forward.

Tip

Validate on a sub-production or development instance before enabling it in production. A feed without filters can bring many credentials on the first run; start with a filter (e.g. credential.types=employee) if you expect a large volume.


Security notes and checklist

Topic

Recommendation

Passwords

Never stored in ServiceNow. Use the fields parameter (step 2.1) so they are not even sent.

Who sees the incidents

Exposed credentials are personal data. Assign the incidents to a restricted group (e.g. with an Assignment group rule) instead of the general queue.

API Key

Stored as password2, readable by admin only, created by a dedicated integration user.

Go-live checklist

  • Credentials feed created in the Axur Platform with the right filters and the fields parameter

  • AxurCredentialFeedMapper Script Include created

  • Pull: properties axur.credentials_feed.url and axur.feed.api_key created

  • Pull: Scheduled Job active · Push: endpoint registered on the feed

  • Tested with ?dry-run=true in axur.credentials_feed.url, no duplicates, no passwords in the Incident

  • ?dry-run=true removed from axur.credentials_feed.url

Did this answer your question?