Skip to content

Implementation / Field notes

Verify authorization before a model-selected tool call

Check the authenticated actor against the requested resource at the tool boundary, rather than trusting account IDs proposed by a model.

By DriftRail · Updated

Authorize a model-selected tool call using the authenticated actor and the actual resource before execution. A model-supplied account ID is an argument to validate, not a source of identity or permission.

Start with a convincing unauthorized argument

Create two synthetic accounts. Authenticate as account A, then propose a well-formed lookup for account B’s record. The argument can pass schema validation and still be unauthorized. The expected boundary is a denial before private data or side effects are returned.

Verify the complete tool boundary

  1. Resolve the actor from trusted server-side session context.
  2. Fetch or evaluate resource permissions using that actor, not another argument copied from model output.
  3. Apply the check on every execution path, including retries, batch operations, and alternate endpoints.
  4. Return a bounded error and record a protected denial reference without leaking the requested private record.

Read the narrow local example

The fixture compares a trusted actor with a resource owner before incrementing a synthetic execution counter. A mismatched account is rejected and leaves the counter at zero; an authorized account proceeds. The example expresses one simple rule, not a complete authorization library or a test of DriftRail’s actual tenant enforcement.

Prefer observable denials over reassuring prose

An assistant’s explanation cannot prove what the server executed. Preserve the authenticated test identity, requested resource reference, policy revision, decision, and final resource state. Keep fixtures free of real customer data and ensure denial logs are themselves access-controlled.

Run the worked example

Save the synthetic Node.js example and run node verify-model-selected-tool-authorization.mjs with Node.js 22 or newer. The assertions check the illustrated records and calculations; they do not test a deployed provider, SDK, or access control. No credentials or network connection are needed.

// Synthetic teaching fixture. No credentials, network calls, or production verification.
import assert from 'node:assert/strict';

const actor = { account: 'a' };
let executions = 0;
const lookup = resource => {
  if (resource.owner !== actor.account) throw new Error('denied');
  executions++;
  return { id: resource.id };
};
assert.throws(() => lookup({ id: 'private-b', owner: 'b' }), /denied/);
assert.equal(executions, 0);
assert.deepEqual(lookup({ id: 'private-a', owner: 'a' }), { id: 'private-a' });
assert.equal(executions, 1);
console.log('Unauthorized proposal produced no lookup execution.');

References and further reading

Maintained by DriftRail. AI assisted the October 2026 content and template revision. Examples are illustrative; they are not measured product benchmarks. Suggest a correction.

From understanding to evidence

Observe your AI in production.

Explore event logging, detections, and review workflows in DriftRail.

Open DriftRail ↗Read the documentation →