Prompt-Injection Exposure Via Input Binding
This page describes the
nowisor-ai-prompt-injection-exposurecheck from the nowisor Instance Scan Pack v1.2.0 (ai-agent-securitygroup, spec AIG-004). The check fires only when BOTH a user-editable free-text field is bound into an agent's prompt context AND that agent holds write ACL reach.
What this finding means
Both conditions must hold on the same entity. The heuristic is fixed by specification:
| # | Condition |
|---|---|
| (a) | an input binding or flow variable maps a user-editable free-text field (work_notes, comments, description, short_description, inbound email body) into the entity's instruction context |
| (b) | that same entity's permission envelope includes write ACL reach on any table |
Either alone is not reported. Free text reaching a read-only agent is a data-disclosure question; write reach without an untrusted source is ordinary configuration. The exposure is the conjunction - untrusted text steering an actor that can change state.
Bindings are read, never inferred. The evidence names the binding, the source field, and the writable target. Where bindings cannot be resolved on the release, the check emits not_applicable with the reason. An agent called "Incident Summarizer" tells us nothing about what it actually reads, and this check never guesses from a name.
Why it matters for your compliance
NIS2 Article 21(2)(e) covers security in development and maintenance - a prompt that accepts untrusted instruction is an input-validation defect in an AI shape. 21(2)(a) covers the risk-analysis obligation.
ISO 27001 A.8.28 (secure coding) is the direct control; injection is injection whether the interpreter is a SQL engine or a model.
DORA Article 9(4)(c) limits access to approved functions - an injected instruction is not an approved function.
OWASP LLM01:2025 (Prompt Injection) is the number-one risk in the list. MITRE ATLAS AML.T0051 (LLM Prompt Injection) and AML.T0053 (AI Agent Tool Invocation) describe the technique and its effect.
The attack path
Step 1 - the attacker writes, not hacks. A user with permission to add a work note types text addressed to the agent rather than to a human. No exploit, no credential, no anomaly - an ordinary field update.
Step 2 - the binding delivers it. The agent's input binding pulls that field into its instruction context. The model cannot reliably distinguish the operator's instructions from text that arrived as data, which is the unsolved property that makes this a design-level exposure rather than a bug.
Step 3 - the confused deputy acts. The agent has write reach. The platform sees a legitimate request from the agent's identity and permits it. The audit trail names the service account, not the note's author - and if the identity is shared across agents, not even which agent.
Why both conditions are required. Condition (a) alone is a disclosure risk. Condition (b) alone is normal. Together they form an injection-to-action path, which is the only version worth a CRITICAL.
How to fix it
Step 1 - remove the untrusted field from the prompt context where the use case does not need it. Often the agent needs a summary or a category, not raw user text.
Step 2 - where it is required, delimit and sanitise so injected text cannot be read as instruction, and constrain what the agent may do with the result.
Step 3 - reduce write reach. An agent that cannot write cannot be steered into writing. This is the structural fix; prompt hardening is a second line.
Step 4 - add a human gate on the write path - see the human-in-the-loop check.
If the check reports N/A: bindings could not be resolved on this release. Review input bindings by hand in AI Agent Studio; do not assume absence of exposure.
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.