AI Agent Runs As Elevated Identity
This page describes the
nowisor-ai-agent-elevated-runascheck from the nowisor Instance Scan Pack v1.2.0 (ai-agent-securitygroup, spec AIA-007). The check flags agentic entities whose execution identity holdsadmin,security_adminor an equivalent elevated role. It reads role grants with their lineage and caps severity at CONDITIONAL where the grants are derived rather than explicit.
What this finding means
One or more agents execute under an identity holding an elevated platform role. An agent's blast radius is its run-as role set, not its prompt. Anything that can steer the agent - a prompt injection in a work note, a poisoned tool description, a misrouted flow - inherits those rights, and the resulting audit trail names the service account rather than whoever supplied the input.
The finding is delegation-aware:
| Grant lineage | Verdict | Reasoning |
|---|---|---|
| at least one explicit grant | CRITICAL (fail) |
somebody deliberately granted this; revoke or justify |
| all derived / out-of-box | CONDITIONAL | the pack cannot read intent for a role it did not observe being granted |
The CONDITIONAL cap exists because rating an OOB-derived inheritance as CRITICAL is precisely the false positive that makes security tooling get ignored. Confirm the role-contains chain named in the evidence before revoking anything.
Why it matters for your compliance
ISO 27001 A.8.2 (privileged access rights) is the control this finding maps to most directly - the 2022 revision separated privileged access from general access precisely because the failure mode differs. An agent is a privileged-access holder that never sleeps and never gets reviewed at a joiner-mover-leaver checkpoint.
NIS2 Article 21(2)(i) and DORA Article 9(4)(c) both require access to be limited to approved functions. An agent with admin has access to every function, approved or not.
OWASP LLM06:2025 (Excessive Agency) is the canonical industry framing. MITRE ATLAS AML.T0012 (Valid Accounts) and AML.T0053 (AI Agent Tool Invocation) describe the adversary techniques.
EU AI Act Article 26 deployer obligations may apply, but only if the deployment qualifies as high-risk under Annex III - most ITSM workflow agents do not, so the mapping is marked conditional.
The attack path
Step 1 - the injection surface. The agent reads a field a lower-privileged user can write: a work note, a description, an inbound email body. See the prompt-injection exposure check for how that surface is enumerated.
Step 2 - the confused deputy. The attacker's text is not addressed to the platform, it is addressed to the agent. The agent has admin. The platform's ACL layer sees a legitimate admin-role request and permits it, because from the platform's perspective that is exactly what it is.
Step 3 - the attribution gap. The write lands with the service account as sys_created_by. Post-incident, you can prove the agent did it. Proving which input caused it requires correlating the agent's execution log to the record it read - which is why the Agent Least-Privilege Report treats log coverage as a first-class precondition.
The mitigation is structural: the agent should not hold the privilege in the first place. Guardrails on the prompt are a second line, not a substitute.
How to fix it
Step 1 - determine actual reach needed. Establish the minimum tables and fields the agent must read and write. The Agent Least-Privilege Report answers this with usage evidence where log coverage permits.
Step 2 - one identity per agent. Create a dedicated service identity and grant only that reach. Do not clone the elevated account's role set (see nowisor-ai-shared-runas-identity for why shared identities make this impossible).
Step 3 - remove the elevated role from the agent's execution identity and re-test the agent's happy path.
If the finding is CONDITIONAL: first establish whether the role inheritance is intentional. Follow the elevated_roles[].lineage values in the evidence - derived_or_oob means no explicit grant record was found, so the role arrived through inheritance you may or may not have designed.
How this check stays honest
Every check in the ai-agent-security group is enumeration-driven: table and
field names are resolved from sys_db_object and sys_dictionary on your
instance, never asserted from a hardcoded list. The sn_aia namespace is
paid-SKU gated and cannot be verified against a ServiceNow developer instance, so
asserting its identifiers from documentation alone would risk exactly the
fabricated-identifier problem this codebase audits for.
Two consequences you will see in the output:
- An absent plugin produces
not_applicable, never a pass. The absence of Now Assist is not a security win; it means the control is out of scope. A check that silently passed would let a customer believe they were assessed on something that was never examined. - An unresolvable field produces
not_applicable, not a finding. Where the release does not expose the column a check needs, the check says so and names it. Firing anyway would flag healthy instances on releases we simply cannot read.
All detection is read-only. No record contents are inspected or transmitted.