{"record":{"id":"0c39edb807b0c21e","repo":"Budibase/budibase","slug":"tool-is-not-available-in-this-security-context-0c39ed","errorCode":null,"errorMessage":"Tool is not available in this security context","messagePattern":"Tool is not available in this security context","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/server/src/ai/tools/index.ts","lineNumber":114,"sourceCode":"  })\n\nconst wrapTool = (\n  toolDef: AiToolDefinition,\n  runtime?: ToolAuthorizationRuntime,\n  gate?: EscalationGateRuntime\n): Tool => {\n  const execute = toolDef.tool.execute\n  if (!execute) {\n    return toolDef.tool\n  }\n\n  const wrappedExecute: NonNullable<Tool[\"execute\"]> = async (\n    input,\n    options\n  ) => {\n    if (runtime) {\n      if (!toolDef.authorization) {\n        throw new Error(\"Tool is not available in this security context\")\n      }\n      await runtime.authorize({\n        authorization: toolDef.authorization,\n        input,\n        executionContext: runtime.executionContext,\n        principal: runtime.principal,\n      })\n    }\n    if (gate) {\n      return await gate.intercept(input, {\n        toolCallId: options?.toolCallId ?? \"\",\n        messages: options?.messages,\n      })\n    }\n    try {\n      const result = await execute(input, options)\n      const failureMessage = getToolFailure(result)\n      if (failureMessage) {","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/ai/tools/index.ts#L96-L132","documentation":"AI tools executed under a runtime security context must declare an authorization configuration. When wrappedExecute detects a runtime (principal/executionContext present) but toolDef.authorization is missing, it refuses to run the tool to prevent unauthorized privileged execution. This guards against tools defined for anonymous/system contexts being invoked in an authenticated security context.","triggerScenarios":"Calling a tool via wrappedExecute when a runtime is set and toolDef.authorization is undefined — e.g. a tool created without the authorization field but executed by an authenticated agent.","commonSituations":"Developer adds a new tool definition and forgets to supply authorization; an existing tool designed for non-runtime contexts is reused inside an authenticated agent runtime; refactoring removed the authorization block.","solutions":["Add an authorization definition to the tool definition (toolDef.authorization) appropriate to the security context","If the tool is intentionally unauthenticated, execute it without a runtime context","Audit the tool factory used to build the tool and ensure it always sets authorization"],"exampleFix":"// before\nconst tool: Tool = { name: \"runQuery\", execute }\n// after\nconst tool: Tool = { name: \"runQuery\", authorization: { /* auth rules */ }, execute }","handlingStrategy":"validation","validationCode":"if (runtime && !toolDef.authorization) throw new Error(\"Tool requires authorization config\")","typeGuard":"const hasAuthorization = (t: Tool): t is Tool & { authorization: NonNullable<Tool[\"authorization\"]> } => !!t.authorization","tryCatchPattern":"try { await wrappedExecute(input, options) } catch (e) { if (e.message.includes(\"security context\")) { /* reconfigure tool auth or drop runtime */ } else throw e }","preventionTips":["Always define authorization when creating tool definitions","Add a factory-level check that authorization is present for runtime-enabled tools","Cover tool creation in unit tests that execute under a runtime"],"tags":["ai","security","authorization"],"backgroundTag":"missing-authorization-config","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}