跳转到正文
报告库
用途分类 / 内容写作

Azure Aigateway Skill 安全审计

作者说它能做什么(原文)

Configure Azure API Management as an AI Gateway for AI models, MCP tools, and agents. WHEN: semantic caching, token limit, content safety, load balancing, AI model governance, MCP rate limiting, jailbreak detection, add Azure OpenAI backend, add AI Foundry model, test AI gateway, LLM policies, configure AI backend, token metrics, AI cost control, convert API to MCP, import OpenAPI to gateway.

第三方安全检查结论

先别安装或运行

已检查文件
9
发现的风险
6
会不会运行危险命令?检查是否下载程序后直接运行、让他人远程控制电脑,或藏起要运行的命令。未发现风险
会不会泄露文件和密钥?检查是否发送含密码或密钥的文件,以及代码里是否直接写了密钥。发现 2 项风险
高风险

共享语义缓存示例没有租户隔离键,可能把一个客户的 AI 答复返回给另一个客户

原文依据:7 处
发现了什么

完整策略在入站阶段按语义相似度查找缓存,并在出站阶段保存答复,但示例没有按订阅、用户或租户划分缓存。多租户示例虽然为限流和指标提取 tenantId,却仍未把它用于缓存。

为什么需要注意

当不同租户提交相似提示时,缓存可能复用包含另一租户上下文、业务数据或个性化内容的答复;较低相似度阈值会扩大错误命中的范围。

这段证据能说明什么

示例确实执行语义缓存查找和存储,且未展示租户键;另一个多租户示例只把 tenantId 用于限流和指标。但所给源码没有说明 APIM 语义缓存的实际隔离范围,因此不能仅凭缺少显式键确认缓存会跨订阅或租户共享。用户应要求作者说明缓存的默认作用域,并在多租户部署前验证隔离行为。

这项判断针对展示的代码和适用条件,不表示风险已经实际发生。
references/policies.md:234来自说明文档打开原文件
        <!-- 2. Semantic Cache Lookup -->        <azure-openai-semantic-cache-lookup            score-threshold="0.8"            embeddings-backend-id="embeddings-backend"            embeddings-backend-auth="system-assigned" />        <!-- 3. Token Rate Limiting -->        <azure-openai-token-limit            tokens-per-minute="50000"            counter-key="@(context.Subscription.Id)"            estimate-prompt-tokens="true" />
查看另外 6 个位置
references/policies.md:268来自说明文档打开原文件
    <outbound>        <base />        <!-- Cache store (after successful response) -->        <azure-openai-semantic-cache-store duration="3600" />    </outbound>
references/patterns.md:201来自说明文档打开原文件
    <base />    <!-- Extract tenant from subscription or header -->    <set-variable name="tenantId" value="@(context.Subscription.Id)" />    <!-- Per-tenant token limit -->    <azure-openai-token-limit        tokens-per-minute="10000"        counter-key="@((string)context.Variables["tenantId"])"        estimate-prompt-tokens="true" />    <!-- Per-tenant metrics -->    <azure-openai-emit-token-metric namespace="ai-gateway">        <dimension name="Tenant" value="@((string)context.Variables["tenantId"])" />
references/troubleshooting.md:84来自说明文档打开原文件
| Cause | Fix ||-------|-----|| `score-threshold` too high | Lower from 0.9 to 0.7 (more matches) || Embeddings backend misconfigured | Verify backend URL and auth || Redis not configured | Deploy Azure Cache for Redis Enterprise with RediSearch || Streaming requests | Semantic caching doesn't work with `"stream": true` |
references/policies.md:68来自说明文档打开原文件
```xml<azure-openai-semantic-cache-lookup    score-threshold="0.8"    embeddings-backend-id="embeddings-backend"    embeddings-backend-auth="system-assigned" />```
references/policies.md:74来自说明文档打开原文件
**Store** (in `<outbound>`):```xml<azure-openai-semantic-cache-store duration="3600" />```
references/patterns.md:202来自说明文档打开原文件
    <!-- Extract tenant from subscription or header -->    <set-variable name="tenantId" value="@(context.Subscription.Id)" />    <!-- Per-tenant token limit -->    <azure-openai-token-limit        tokens-per-minute="10000"        counter-key="@((string)context.Variables["tenantId"])"        estimate-prompt-tokens="true" />    <!-- Per-tenant metrics -->    <azure-openai-emit-token-metric namespace="ai-gateway">        <dimension name="Tenant" value="@((string)context.Variables["tenantId"])" />        <dimension name="API" value="@(context.Api.Name)" />
高风险

诊断步骤会把内置全访问订阅的主密钥输出为明文

原文依据:2 处
发现了什么

命令明确查询 Built-in all-access subscription 的 primaryKey 并以纯文本输出,随后要求把它放进 curl 请求头。该密钥的权限范围明显高于单一 API 的普通测试凭据。

为什么需要注意

密钥可能被终端回滚、命令记录、CI 日志、屏幕共享或复制粘贴记录保存;获得它的人可能以该全访问订阅调用 APIM API并启用追踪。

排障命令选择内置 all-access 订阅的 primaryKey,并以 TSV 形式输出,然后要求把该值放入请求头。执行时,密钥会出现在终端输出,也可能进入 shell 历史、日志或录屏;泄露者可能获得该订阅所覆盖的广泛网关访问。用户应要求使用专用、最小权限且短期的测试订阅,并避免显示或记录主密钥。

references/troubleshooting.md:203来自说明文档打开原文件
### APIM TracingEnable request tracing for debugging policy flow:```bash# Get tracing subscription keyaz apim subscription list --service-name <apim> --resource-group <rg> \  --query "[?displayName=='Built-in all-access subscription'].primaryKey" -o tsv# Send request with tracingcurl -X POST "${GATEWAY_URL}/..." \  -H "Ocp-Apim-Trace: true" \  -H "Ocp-Apim-Subscription-Key: <built-in-key>"```
查看另外 1 个位置
references/troubleshooting.md:212来自说明文档打开原文件
# Send request with tracingcurl -X POST "${GATEWAY_URL}/..." \  -H "Ocp-Apim-Trace: true" \  -H "Ocp-Apim-Subscription-Key: <built-in-key>"```
会不会删除文件或一直在后台运行?检查是否大范围删除文件、改写磁盘,或设置自动启动。未发现风险
会不会绕过安全保护?检查是否跳过网站安全验证、开放过多文件权限,或取消操作前的确认。发现 4 项风险
高风险

按客户端提供的 X-Agent-Id 或 X-User-Id 限流可被伪造,从而绕过配额并影响其他身份

原文依据:2 处
发现了什么

示例直接把请求头值作为限流计数键,没有先展示认证、签名验证或把该值绑定到已验证身份。调用者可不断更换头值来获得新的计数桶,也可冒用他人的标识消耗其配额。

为什么需要注意

攻击者可能绕过 MCP/API 调用限制、增加模型费用和后端负载,或通过冒用标识使合法用户遭遇 429。

两个活动配置示例直接采用请求方可提供的 X-Agent-Id 或 X-User-Id 作为计数键,所示代码未先验证这些标头或绑定到已认证身份。若网关允许客户端自行设置它们,客户端可轮换值绕过单桶限额,或使用他人的值消耗其配额。用户应限制这些标头由可信代理写入,或改用经验证的订阅/身份声明。

references/patterns.md:160来自说明文档打开原文件
```xml<!-- Rate limit MCP tool calls --><inbound>    <base />    <rate-limit-by-key calls="10" renewal-period="60"        counter-key="@(context.Request.Headers.GetValueOrDefault("X-Agent-Id", "anonymous"))" /></inbound>```
查看另外 1 个位置
references/troubleshooting.md:48来自说明文档打开原文件
```xml<!-- Per-user instead of global --><azure-openai-token-limit    tokens-per-minute="50000"    counter-key="@(context.Request.Headers.GetValueOrDefault("X-User-Id", context.Subscription.Id))"    estimate-prompt-tokens="true" />```
中风险

角色授予和身份启用会持续扩大 APIM 的权限,错误资源标识可能授权到非预期主体或范围

原文依据:2 处
发现了什么

步骤先启用系统分配身份,再把 Cognitive Services User 角色授予变量中的主体和资源。命令是实际 Azure 控制面变更;占位符或当前订阅/租户选择错误时,结果不会局限于文档演示。

为什么需要注意

APIM 会获得调用目标认知服务的持续权限;选择错误的 principal、resource group、订阅或资源 ID 可能让非预期网关访问模型并产生费用。

这段代码的正常用途

这些是明确标注的后端接入步骤:先启用 APIM 托管身份,再在具体 AOAI 资源 ID 的 scope 上授予 Cognitive Services User。它们确实会持久修改 Azure 配置,但与该技能声明的网关配置目的相符,且使用显式占位符,并非隐蔽扩大权限。用户仍应在执行前核对当前租户、订阅、主体 ID 和资源级 scope,并由具备授权的管理员批准。

这项判断针对展示的代码和适用条件,不表示风险已经实际发生。
references/patterns.md:29来自说明文档打开原文件
#### 2. Enable Managed Identity on APIM```bash# Enable system-assigned identityaz apim update --name <apim-name> --resource-group <rg> --set identity.type=SystemAssigned# Get principal IDPRINCIPAL_ID=$(az apim show --name <apim-name> --resource-group <rg> --query "identity.principalId" -o tsv)```
查看另外 1 个位置
references/patterns.md:39来自说明文档打开原文件
#### 3. Grant RBAC Access```bashAOAI_ID=$(az cognitiveservices account show --name <aoai-name> --resource-group <rg> --query id -o tsv)az role assignment create \  --assignee "$PRINCIPAL_ID" \  --role "Cognitive Services User" \  --scope "$AOAI_ID"```
中风险

API 导入直接信任 GitHub main 分支上的远程规范,内容变化可未经审查进入网关配置

原文依据:1 处
发现了什么

命令让 Azure APIM 从 raw.githubusercontent.com 的 main 分支下载并导入 OpenAPI 文件,未固定提交哈希,也未要求先下载、校验和审查。远程内容可随分支更新而变化。

为什么需要注意

以后运行同一命令可能导入不同的路径、操作或架构,意外扩大对外暴露的 API 表面或改变客户端可调用的操作。

导入命令让 APIM 直接从 GitHub main 分支的 raw URL 获取 OpenAPI 规范;该引用未固定提交版本,也未展示下载、校验或人工审查步骤。若上游分支内容改变,之后执行可能导入与此前不同的 API 定义,影响网关暴露的操作和路由。用户可要求固定到已审查的提交及文件哈希,并在导入前保存和检查规范。

references/patterns.md:61来自说明文档打开原文件
#### 5. Import API (OpenAPI Spec)```bash# Import the Azure OpenAI API specificationaz apim api import \  --service-name <apim-name> \  --resource-group <rg> \  --api-id azure-openai-api \  --path "openai" \  --specification-format OpenApi \  --specification-url "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cognitiveservices/data-plane/AzureOpenAI/inference/stable/2024-02-01/inference.json" \  --service-url "https://<aoai-name>.openai.azure.com/openai"```
中风险

排障建议通过提高内容安全阈值来减少误报,会明确放宽有害内容过滤

原文依据:4 处
发现了什么

文档说明阈值 0 表示全部阻止、6 表示允许大多数内容;排障步骤把所有类别从 4 提高到 5,并在快速表中建议提高到 5–6。该调整不仅解决误报,也会增加有害内容通过的概率。

为什么需要注意

仇恨、色情、自残或暴力内容可能更容易到达模型或最终用户;若运营人员把它作为通用修复直接应用,安全和合规边界会在没有风险评估的情况下改变。

源码定义阈值 0 为全部阻止、6 为允许大多数内容,并在误报排障中把所有类别从 4 提高到 5,明确标注为“less strict”。这会减少误报,但也可能让更严重的仇恨、色情、自残或暴力内容通过;主技能还概括建议提高到 5–6。用户应要求按类别用代表性测试集评估,并通过审批和监控逐步调整,而非统一放宽。

references/policies.md:149来自说明文档打开原文件
| Category | Description | Threshold Range ||----------|-------------|-----------------|| Hate | Discrimination, slurs | 0 (block all) - 6 (allow most) || Sexual | Explicit content | 0-6 || SelfHarm | Self-injury content | 0-6 || Violence | Violent content | 0-6 |
查看另外 3 个位置
references/troubleshooting.md:120来自说明文档打开原文件
**Solutions**:1. **Increase thresholds** (less strict):```xml<llm-content-safety backend-id="contentsafety-backend">    <category name="Hate" threshold="5" />      <!-- Was 4, now less strict -->    <category name="Sexual" threshold="5" />    <category name="SelfHarm" threshold="5" />    <category name="Violence" threshold="5" /></llm-content-safety>```
SKILL.md:107来自说明文档打开原文件
| Issue | Solution ||-------|----------|| Token limit 429 | Increase `tokens-per-minute` or add load balancing || No cache hits | Lower `score-threshold` to 0.7 || Content false positives | Increase category thresholds (5-6) || Backend auth 401 | Grant APIM "Cognitive Services User" role |
references/troubleshooting.md:116来自说明文档打开原文件
### False Positives (Legitimate Content Blocked)**Symptom**: Normal business content is being blocked by content safety policy.**Solutions**:1. **Increase thresholds** (less strict):```xml<llm-content-safety backend-id="contentsafety-backend">    <category name="Hate" threshold="5" />      <!-- Was 4, now less strict -->    <category name="Sexual" threshold="5" />    <category name="SelfHarm" threshold="5" />    <category name="Violence" threshold="5" /></llm-content-safety>
会不会误导 AI 或隐藏内容?检查工作说明是否要求 AI 忽略你的指令、干扰检查结果,或夹带看不见的文字。未发现风险
会不会偷偷改推广链接或收款方?检查是否强制替换推广链接或收款对象,同时要求隐瞒更改。未发现风险

Skill 逻辑拆解

8 个说明模块

此 Skill 主要提供可直接运行的 Azure CLI、curl 和 APIM XML 示例;其中一些命令不只是检查状态,还会启用托管身份、创建后端、授予角色并导入 API,因此使用它可能持续改变 Azure 资源。

查看原文
references/patterns.md:29来自说明文档打开原文件
#### 2. Enable Managed Identity on APIM```bash# Enable system-assigned identityaz apim update --name <apim-name> --resource-group <rg> --set identity.type=SystemAssigned# Get principal IDPRINCIPAL_ID=$(az apim show --name <apim-name> --resource-group <rg> --query "identity.principalId" -o tsv)```
references/patterns.md:39来自说明文档打开原文件
#### 3. Grant RBAC Access```bashAOAI_ID=$(az cognitiveservices account show --name <aoai-name> --resource-group <rg> --query id -o tsv)az role assignment create \  --assignee "$PRINCIPAL_ID" \  --role "Cognitive Services User" \  --scope "$AOAI_ID"```

推荐的治理链会以 APIM 托管身份调用认知服务,并可把提示的语义缓存一小时;它还向 Azure Monitor发送订阅、API、模型和操作维度的令牌用量指标。

查看原文
references/policies.md:67来自说明文档打开原文件
```xml<azure-openai-semantic-cache-lookup    score-threshold="0.8"    embeddings-backend-id="embeddings-backend"    embeddings-backend-auth="system-assigned" />```**Store** (in `<outbound>`):```xml<azure-openai-semantic-cache-store duration="3600" />```
references/policies.md:107来自说明文档打开原文件
```xml<azure-openai-emit-token-metric namespace="ai-gateway">    <dimension name="Subscription" value="@(context.Subscription.Id)" />    <dimension name="API" value="@(context.Api.Name)" />    <dimension name="Model" value="@(context.Request.Headers.GetValueOrDefault("x-model", "unknown"))" />    <dimension name="Operation" value="@(context.Operation.Id)" /></azure-openai-emit-token-metric>```

它包含读取普通订阅密钥以及内置全访问订阅主密钥的命令,并展示把这些密钥用于网关请求。输出和后续请求可能进入终端记录或自动化日志。

查看原文
SKILL.md:51来自说明文档打开原文件
# Get subscription keyaz apim subscription keys list \  --service-name <apim-name> --resource-group <rg> --subscription-id <sub-id>```
references/troubleshooting.md:207来自说明文档打开原文件
```bash# Get tracing subscription keyaz apim subscription list --service-name <apim> --resource-group <rg> \  --query "[?displayName=='Built-in all-access subscription'].primaryKey" -o tsv# Send request with tracingcurl -X POST "${GATEWAY_URL}/..." \  -H "Ocp-Apim-Trace: true" \  -H "Ocp-Apim-Subscription-Key: <built-in-key>"```

该 Skill 不包含自动执行脚本;所示安装步骤是常规 Azure SDK 包安装,所示网络请求指向 Azure 服务、Microsoft 文档或 Azure 的 GitHub 规范。可见内容中没有向陌生接收方上传本地文件或凭据的指令。

查看原文
references/sdk/azure-ai-contentsafety-py.md:6来自说明文档打开原文件
## Install```bashpip install azure-ai-contentsafety```
references/sdk/azure-ai-contentsafety-ts.md:6来自说明文档打开原文件
## Install```bashnpm install @azure-rest/ai-content-safety @azure/identity @azure/core-auth```
从这里开始 · 工作说明SKILL.md
azure-aigateway
连线表示工作说明包含的模块,不是实际运行顺序。点击模块可查看原文。

文件引用关系图

11 处引用
哪些文件发起引用引用了什么
连线表示真实的文件引用,不是运行顺序。点击节点可高亮相关连线,并查看具体文件和原文位置。虚线表示还有文件需要定位。
文件与检查记录9 个文件

检查范围与遗漏

逐文件查看涉及的内容

下方列出本次涉及的原文范围;纳入检查不代表已查清所有问题。

  • SKILL.md已纳入全文
  • references/patterns.md已纳入全文
  • references/policies.md已纳入全文
  • references/sdk/azure-ai-contentsafety-py.md已纳入全文
  • references/sdk/azure-ai-contentsafety-ts.md已纳入全文
  • references/sdk/azure-mgmt-apimanagement-dotnet.md已纳入全文
  • references/sdk/azure-mgmt-apimanagement-py.md已纳入全文
  • references/troubleshooting.md已纳入全文
  • references/auth-best-practices.md已纳入全文

这份报告只针对上方版本。我们看了拿到的代码和说明文件,没有实际运行 Skill,也没有检查它另外安装的软件包。因此,这不是“保证安全”的承诺;换了版本或使用环境,结果也可能不同。

  • SKILL.md工作说明
  • references/auth-best-practices.md配套文件
  • references/patterns.md配套文件
  • references/policies.md配套文件
  • references/sdk/azure-ai-contentsafety-py.md配套文件
  • references/sdk/azure-ai-contentsafety-ts.md配套文件
  • references/sdk/azure-mgmt-apimanagement-dotnet.md配套文件
  • references/sdk/azure-mgmt-apimanagement-py.md配套文件
  • references/troubleshooting.md配套文件

代码和说明中提到的操作

连接外部网站
SKILL.md:15来自说明文档打开原文件
> **To deploy APIM**, use the **azure-prepare** skill. See [APIM deployment guide](https://learn.microsoft.com/azure/api-management/get-started-create-service-instance).
SKILL.md:63来自说明文档打开原文件
curl -X POST "${GATEWAY_URL}/openai/deployments/<deployment>/chat/completions?api-version=2024-02-01" \  -H "Content-Type: application/json" \
SKILL.md:83来自说明文档打开原文件
az apim backend create --service-name <apim> --resource-group <rg> \  --backend-id openai-backend --protocol http --url "https://<aoai>.openai.azure.com/openai"
运行命令
SKILL.md:43来自说明文档打开原文件
```bash# Get gateway URL
SKILL.md:60来自说明文档打开原文件
```bashGATEWAY_URL=$(az apim show --name <apim-name> --resource-group <rg> --query "gatewayUrl" -o tsv)
SKILL.md:77来自说明文档打开原文件
```bash# Discover AI resources
读取密钥或账号配置
references/auth-best-practices.md:16来自说明文档打开原文件
| **CI/CD pipelines** | `AzurePipelinesCredential` / `WorkloadIdentityCredential` | Scoped to pipeline identity || **Local development** | `DefaultAzureCredential` | Chains CLI, PowerShell, and VS Code credentials for convenience |
references/auth-best-practices.md:32来自说明文档打开原文件
var credential = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT") == "Development"    ? new DefaultAzureCredential()                          // local dev — uses CLI/VS credentials
references/auth-best-practices.md:33来自说明文档打开原文件
var credential = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT") == "Development"    ? new DefaultAzureCredential()                          // local dev — uses CLI/VS credentials    : new ManagedIdentityCredential();                      // production — deterministic, no fallback chain
安装其他软件包
references/sdk/azure-ai-contentsafety-py.md:8来自说明文档打开原文件
```bashpip install azure-ai-contentsafety```
references/sdk/azure-ai-contentsafety-ts.md:8来自说明文档打开原文件
```bashnpm install @azure-rest/ai-content-safety @azure/identity @azure/core-auth```
references/sdk/azure-mgmt-apimanagement-py.md:8来自说明文档打开原文件
## Installpip install azure-mgmt-apimanagement azure-identity
读取了多少行
1,188
文件校验值(用于核对版本)
11ab38b45787f6703a021d2aa3eb31cc222980a39ab06a393d092626977f8219