DEV Community

Cover image for Best practices for implementing LLM access controls and monitoring
RESK
RESK

Posted on

Best practices for implementing LLM access controls and monitoring

The question

Teams ask a version of the same thing: we wired an LLM to tools, it works, what do we actually have to build before we ship it. This article answers that with the concrete ordering and the failure modes, not with a maturity model.

What AI agent security means here

An AI agent is a model that can emit actions. The model itself is stateless text generation. The security problem starts at the boundary where generated text becomes a tool invocation, a database query, a file read, an HTTP request.

That boundary is where you own the risk. The model will produce whatever token sequence is most probable given its context. It has no concept of your authorization model. If your handler executes what the model emits, the model is effectively your authorization layer, and it is not one.

The attack surface, concretely

Three things go wrong repeatedly.

Confused deputy. The agent runs with the credentials of the service hosting it. A user who is only allowed to read triggers a tool that writes. The tool does not know the difference because the identity it sees is the service account.

Scope creep through arguments. The tool is permitted, the identity is permitted, but the argument is not. A search tool called with a filter that reaches a tenant it should not. A file tool called with a path that escapes the intended directory.

Silent success. The call was blocked, or should have been, and nothing recorded why. Weeks later nobody can distinguish a denied attack from a broken integration, so the block gets removed to make the dashboard green.

None of this requires a novel exploit. It requires a tool call that was authorized at the wrong granularity.

The mechanism that stops it

Put the decision in the request path, before execution, and make it ordered.

  1. Identity. Resolve who is asking. Not the service account. The end user or the workload that originated the request, propagated through the agent.
  2. Tool. Is this identity allowed to invoke this tool at all.
  3. Resource. Is this tool allowed to touch this resource for this identity.
  4. Arguments. Does this specific argument set stay inside the granted scope.

If any step fails, the call does not reach the executor. The order matters: checking arguments before identity means you are validating input for an actor you have not authenticated.

Monitoring is the same decision stream, written down. For every tool call record the identity, the tool, the resource, the arguments, the decision, and the reason. The reason is the part teams skip and the part that makes the log usable.

A concrete failure mode

Consider a support agent with a ticket lookup tool and a ticket update tool. A user asks it to summarize a ticket. The model, trying to be helpful, also calls the update tool to add a note.

The handler executes both. The service account has write access. The user did not. Nothing in the prompt was malicious. The authorization check that would have caught it was never in the path.

With the ordering above, step two fails: this identity is not allowed to invoke the update tool. The call is denied, the reason is logged, and the summary still returns.

Implementation with RESK

reskSecure enforces the ordered decision before the tool executes, so the executor only ever sees calls that passed identity, tool, resource and argument checks. It is the enforcement point, not a scanner that reports after the fact.

ReskPoints provides the monitoring side: the decision stream with identity, tool, resource, arguments, outcome and reason, so a denial is visible as a denial rather than as an error rate.

For the permission model itself, the tool permission design is covered separately in AI agent tool permissions. Read that first if you have not defined what each tool is allowed to do.

Enforce least privilege on your agents: https://resk.fr/projects/resksecure.html

Checklist

  • Every tool call carries the originating identity, not the host service account.
  • Authorization runs before execution, in the order identity, tool, resource, arguments.
  • Argument scope is validated against the granted scope, not against a global allowlist.
  • Denials are logged with a reason, distinct from errors.
  • The log records identity, tool, resource, arguments, decision and reason for every call.
  • Removing a control requires a recorded reason, so a block is never deleted to clear a dashboard.
  • Tool permissions are defined per tool before the agent is connected to it.

Top comments (0)