Back to skill

Security audit

ServiceNow Agent

Security checks for vulnerabilities and agentic risk

Overview

This ServiceNow skill appears intended as a read-only CLI, but its credential handling, broad ServiceNow access, and conflicting API references need careful review before installation.

Install only if you are comfortable giving the skill a dedicated, least-privilege, read-only ServiceNow account. Use HTTPS-only domains, avoid command-line passwords, keep .env out of shared folders and version control, and treat ticket history, work notes, and attachments as sensitive data. Do not rely on the included API reference files as a safe read-only surface unless the mutating operations are removed or technically blocked.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
cli.mjs:55
Finding
Basic Authentication Credentials May Be Transmitted over Plaintext HTTP## Vulnerability Details **File Location**: `cli.mjs:55-58`, with credential transmission at `cli.mjs:199-206` and `cli.mjs:215-221` **Vulnerability Type**: Insecure transport of reusable credentials **Risk Level**: High ### Vulnerable Code ```js function buildBaseUrl(domain) { if (!domain) return ''; if (domain.startsWith('http://') || domain.startsWith('https://')) return domain.replace(/\/$/, ''); return `https://${domain.replace(/\/$/, '')}`; } ``` ```js async function requestJson(baseUrl, username, password, pathAndQuery) { const auth = Buffer.from(`${username}:${password}`).toString('base64'); const url = `${baseUrl}${pathAndQuery}`; const response = await fetch(url, { headers: { 'Accept': 'application/json', 'Authorization': `Basic ${auth}`, }, }); const text = await response.text(); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${text.slice(0, 500)}`); } return text; } async function requestBinary(baseUrl, username, password, pathAndQuery) { const auth = Buffer.from(`${username}:${password}`).toString('base64'); const url = `${baseUrl}${pathAndQuery}`; const response = await fetch(url, { headers: { 'Authorization': `Basic ${auth}`, }, }); ``` ### Technical Analysis The URL builder explicitly accepts both HTTPS and plaintext HTTP URLs. The request functions then place the configured ServiceNow username and password in an HTTP Basic Authentication header for every request. Basic Authentication only Base64-encodes the credentials; it does not encrypt them. If the configured domain uses `http://`, any party able to observe or modify the network connection can recover the original username and password. This is unnecessary for the declared functionality because ServiceNow API authentication can and should be restricted to HTTPS. The destination is user-configurable. No hidden third-party exfiltration endpoint was found, but the lack of transport enforcement makes the ...[truncated 1235 chars]
Remediation
## Remediation Suggestions - Parse the configured base URL with the standard `URL` class and reject every protocol other than `https:`. - Reject URLs containing embedded usernames or passwords. - Consider restricting destination hostnames to an organization-managed allowlist or an approved ServiceNow domain suffix. - Do not silently downgrade or redirect authenticated requests to HTTP. Explicitly verify redirect behavior for credential-bearing requests. - Prefer scoped, short-lived OAuth tokens over reusable account passwords. - Require a dedicated ServiceNow account with server-enforced read-only roles; do not rely solely on the CLI’s use of GET. - Add automated tests proving that `http://` URLs, malformed URLs, and redirects to non-HTTPS destinations are rejected before an Authorization header is sent. A hardened URL builder should follow this pattern: ```js function buildBaseUrl(domain) { if (!domain) return ''; const candidate = /^[a-z][a-z0-9+.-]*:\/\//i.test(domain) ? domain : `https://${domain}`; const url = new URL(candidate); if (url.protocol !== 'https:') { throw new Error('Only HTTPS ServiceNow endpoints are allowed'); } if (url.username || url.password) { throw new Error('Credentials must not be embedded in the ServiceNow URL'); } return url.origin; } ```

T09 · Insecure Skill Coding Practices

Warning
Location
cli.mjs:149
Finding
Command-Line Password Support Exposes ServiceNow Credentials to Local Observation and Logging## Vulnerability Details **File Location**: `cli.mjs:149-152` and `cli.mjs:171-175`; documented usage at `SKILL.md:153-156` **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```js function resolveAuth(args, dotenv) { const domain = args.domain || process.env.SERVICENOW_DOMAIN || dotenv.SERVICENOW_DOMAIN; const username = args.username || args.user || process.env.SERVICENOW_USERNAME || dotenv.SERVICENOW_USERNAME; const password = args.password || args.pass || process.env.SERVICENOW_PASSWORD || dotenv.SERVICENOW_PASSWORD; return { domain, username, password }; } ``` ```js Auth (flags override env): --domain <domain> ServiceNow instance domain --username <user> Basic auth username (alias: --user) --password <pass> Basic auth password (alias: --pass) ``` The Skill documentation explicitly recommends the affected invocation pattern: ```bash node cli.mjs list incident --domain myinstance.service-now.com --username admin --password "***" --sysparm_limit 3 ``` ### Technical Analysis The CLI accepts ServiceNow passwords through `--password` and `--pass`. Command-line arguments are commonly retained in shell history and may be visible through process inspection, endpoint monitoring, job-runner metadata, audit logs, debugging output, or automation telemetry. This exposure is avoidable because the CLI already supports environment-based and `.env`-based authentication. Environment variables are not a complete secret-management solution, but they generally avoid direct inclusion in command history and ordinary process command-line displays. The documentation increases the likelihood of exploitation by presenting command-line password use as an approved authentication mechanism. ### Attack Path 1. A user follows the documented example and supplies a real password through `--password` or `--pass`. 2. The shell stores the invocation in command history, or a process moni ...[truncated 1071 chars]
Remediation
## Remediation Suggestions - Remove support for `--password` and `--pass`. - Remove the command-line password example from `SKILL.md`. - Obtain secrets from an operating-system credential store, dedicated secret manager, or interactive hidden prompt. - If environment variables remain supported, document their limitations and avoid printing inherited environments in diagnostics. - If `.env` remains supported: - Require restrictive permissions such as owner read/write only. - Ensure `.env` is excluded from version control. - Avoid placing it in shared project directories. - Prefer short-lived, scoped OAuth credentials instead of a reusable account password. - Use a dedicated account with server-side read-only roles and rotate any credential previously supplied on a command line. - Add documentation warning users never to include passwords in shell commands, scripts, issue reports, or logs.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (22)

YARA rule 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Content
_text',
    'sysparm_offset',
    'sysparm_category',
    'sysparm_type',
    'sysparm_catalog',
    'sysparm_top_level_only',
    'record_id',
    'template_id',
    'mode',
  ];
  for (const key of allowed) {
    if (params[key] !== undefined) {
      query.set(key, String(params[key]));
    }
  }
  return query.toString();
}

function resolveAuth(args, dotenv) {
  const domain = args.domain || process.env.SERVICENOW_DOMAIN || dotenv.SERVICENOW_DOMAIN;
  const username = args.username || args.user || process.env.SERVICENOW_USERNAME || dotenv.SERVICENOW_USERNAME;
  const password = args.password || args.pass || process.env.SERVICENOW_PASSWORD || dotenv.SERVICENOW_PASSWORD;
  return { domain, username, password };
}

function formatHelp() {
  return `ServiceNow Table API CLI (read-only)

Usage:
  cli.mjs list <table> [options]
  cli.mjs get <table> <sys_id> [options]
  cli.mjs batch <file.json> [options]
  cli.mjs attach list [options]
  cli.mjs attach get <sys_id>
  cli.mjs attach fil
Confidence
85% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Credential Access

High
Category
Privilege Escalation
Content
## Configuration

Set these environment variables in the .env file in this folder.

- SERVICENOW_DOMAIN instance domain such as myinstance.service-now.com
- SERVICENOW_USERNAME username for basic auth
Confidence
91% confidence
Finding
The skill instructs users to place ServiceNow username and password credentials in a local .env file for basic authentication. Storing reusable credentials in plaintext configuration raises the risk of credential theft through local compromise, accidental commit, log exposure, or unintended access by other tools running in the same environment.

Credential Access

High
Category
Privilege Escalation
Content
## CLI

Use the bundled CLI for all reads. It pulls auth from .env by default. You can override with flags.

### Command overview
Confidence
95% confidence
Finding
The CLI pulls authentication from .env by default and also allows overriding credentials directly on the command line with --username and --password. Command-line credentials are especially dangerous because they can be exposed via shell history, process listings, audit logs, screenshots, and copied examples, increasing the chance of credential compromise.

Credential Access

High
Category
Privilege Escalation
Content
return;
  }

  const dotenv = loadDotEnv(path.join(__dirname, '.env'));
  const { domain, username, password } = resolveAuth(args, dotenv);
  const baseUrl = buildBaseUrl(domain);
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The OpenAPI spec explicitly exposes POST upload endpoints and a DELETE endpoint even though the skill metadata claims the capability is read-only. This mismatch is dangerous because an agent or integrator relying on the manifest could invoke mutation and destructive attachment actions against ServiceNow records, causing unauthorized data creation or deletion.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The skill is described as read-only, but this OpenAPI spec exposes numerous POST, PUT, and DELETE endpoints such as checkout, submit_order, order_now, add_to_cart, and delete operations. This mismatch can cause an agent or integrator to invoke state-changing ServiceNow actions under the false assumption that the integration is safe for read-only use, leading to unauthorized purchases, request creation, cart mutation, or record deletion.

Missing User Warnings

High
Confidence
98% confidence
Finding
Checkout and submit_order endpoints can create real downstream service requests, but the spec provides no user-facing warnings or safety constraints. In the context of an agent skill, silent exposure of these operations materially increases the risk of unauthorized ordering, accidental procurement, or business workflow execution.

Missing User Warnings

High
Confidence
98% confidence
Finding
The spec includes DELETE operations affecting cart and item resources without any warning that they are destructive. In a supposedly read-only skill, this is especially dangerous because users and orchestrators may not defend against deletion paths, enabling data loss or disruption of in-progress requests.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The API description states it allows CRUD operations on existing tables, directly contradicting the skill's stated read-only intent. In agent settings, these documentation contradictions are dangerous because tool-selection and human trust may rely on the declared safety profile, masking destructive capabilities.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The OpenAPI spec explicitly exposes POST, PUT, PATCH, and DELETE operations while the skill metadata claims the capability is read-only. This mismatch can cause an agent or integrator to invoke state-changing ServiceNow actions unexpectedly, leading to unauthorized record creation, modification, or deletion in a sensitive enterprise system.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill invokes a bundled CLI that uses environment variables for authentication and makes outbound requests to a ServiceNow instance, but the skill metadata does not declare any explicit tool scope or permission boundaries. That creates a governance gap: an agent may be able to access env-backed credentials and network egress without clear policy constraints or user visibility.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill explicitly encourages downloading attachments and reading full ticket history, which commonly contain sensitive data such as credentials, tokens, customer information, internal screenshots, and work notes, but it does not warn about data sensitivity or handling requirements. In an agent context, this increases the chance of over-collection, accidental disclosure in logs, or unsafe summarization of confidential material.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The skill is described as read-only, but it exposes Service Catalog endpoints such as cart, wishlist, delivery-address, and related resources that are commonly associated with user state and workflow interactions rather than passive inspection. Even though this implementation uses GET requests only, surfacing these endpoints in a supposedly read-only tool expands capability beyond the stated trust boundary and may trigger unintended stateful actions depending on ServiceNow endpoint behavior or side effects.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The file description states the API allows upload, download, and removal of attachments, which directly contradicts the skill's documented read-only purpose. This is a security-relevant documentation integrity issue because it signals that the effective capability surface is broader than users and downstream tooling may expect.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The spec exposes a DELETE attachment operation without any corresponding user-facing warning or indication in the skill metadata that destructive actions are possible. In the context of a supposedly read-only ServiceNow skill, this increases the chance of accidental or unauthorized deletion of evidence, records, or operational artifacts.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The API documentation broadly states that it allows use of the Service Catalog via REST, while the surrounding skill metadata claims read-only access. That ambiguity is dangerous because agents and users may rely on the safer claim while the underlying API surface includes write operations, increasing the chance of unintended privileged actions.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The spec exposes checkout and order-submission functionality without warning text, approval language, or visible scope constraints. In an agent setting, that creates a workflow safety issue where a model could trigger real service requests or purchases without adequate user awareness or confirmation.

Vague Triggers

Medium
Confidence
93% confidence
Finding
Several mutating endpoints have empty descriptions, so their operational effect is not clearly documented. Poorly described write operations increase the chance that an agent or developer will misuse them, accidentally modifying carts, items, or requests without understanding consequences.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The specification grants access to arbitrary `{tableName}` values and describes CRUD on existing tables without any documented allowlist, role boundary, or context restriction. In ServiceNow, this broad scope can expose sensitive HR, security, incident, or configuration data and may permit high-impact changes if paired with write methods.

Context-Inappropriate Capability

Low
Confidence
88% confidence
Finding
The manifest speaks to read-only CLI access to ServiceNow APIs, but the code adds a local secret-loading mechanism by parsing a .env file from disk. Handling local credential files is not part of the stated business purpose and expands the skill's capability surface beyond simply querying ServiceNow.

Vague Triggers

Low
Confidence
87% confidence
Finding
This manifest-style file says the API "Allows you to upload, download, and remove attachments" but does not define any specific activation phrases, scope limits, or exclusion conditions. In a skill-selection context, such a broad description can overlap with many common attachment-related requests and increase the chance of unintended invocation.

Vague Triggers

Low
Confidence
71% confidence
Finding
Descriptions such as "Create a record," "Modify a record," "Update a record," and "Delete a record" are very generic in a manifest-style API definition. Without contextual constraints, these broad action labels do not help distinguish intended use from ordinary requests to create, update, or delete data.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
cli.mjs:149