把 Agent 当作身份审计,收紧模型调用权限
主张将自建及随工具引入的 Agent 都视为具有权限和网络路径的非人类身份。通过 Bedrock IAM 配置示例,展示限定具体模型 ARN 与通配授权的区别,避免任务被攻陷后调用昂贵模型。
AI 深度解读
给 AI Agent 限制 Secrets Manager 权限,就能保证它读不到生产密钥吗?作者审查自己的 AWS 配置后发现:Agent 虽然不能直接读取那些密钥,却能进入已经注入密钥的生产容器,绕过纸面上的限制。
这篇文章讨论的是 Agent 背后的身份与权限。它的核心判断是:审计不能止于一份 IAM policy,还要沿着容器、部署流水线、OAuth 连接器继续追踪,查清 Agent 最终能碰到什么。
不能直接读密钥,不代表拿不到密钥
作者给代码 Agent 配置的秘密读取权限看起来很克制:secretsmanager:GetSecretValue 只允许访问 /myapp/agent-box-github-token-* 和 /myapp/agent-box-claude-credentials-*。写入更窄,PutSecretValue 只用于更新凭据,避免失控会话覆盖 GitHub token。
问题出在同一个角色的其他权限上。
为了排查生产问题,这个角色还获得了 ecs:ExecuteCommand、ecs:DescribeServices、ecs:DescribeTasks,以及 ecs:RegisterTaskDefinition、ecs:UpdateService、ecs:RunTask、ecs:StopTask、ecs:TagResource。相关配置的 resources 都是 ["*"]。
下面这条命令用于检查角色对关键操作的权限:
aws iam simulate-principal-policy \
--policy-source-arn "$AGENT_ROLE_ARN" \
--action-names ecs:ExecuteCommand ecs:UpdateService ecs:RegisterTaskDefinition \
secretsmanager:GetSecretValue iam:PassRole \
--resource-arns "*" \
--query 'EvaluationResults[].[EvalActionName,EvalDecision]' --output text
要留意 --resource-arns "*":它检查的是指定资源表达式下的结果,不能直接代表所有具体资源、所有条件下的结论。
作者得到的输出是:
ecs:ExecuteCommand allowed
ecs:UpdateService allowed
ecs:RegisterTaskDefinition allowed
secretsmanager:GetSecretValue implicitDeny
iam:PassRole implicitDeny
关键在第一行。生产 backend 容器启动时,会从 Secrets Manager 注入 DB_USER、DB_PASSWORD、JWT_PRIVATE_KEY 和 STRIPE_SECRET_KEY。Agent 可以通过 ECS Exec 进入容器,再用 env 接近这些秘密。
这条路径已经用于生产环境的临时查询,是作者记录过的操作流程。
最后一行也不能照单全收。作者指出,iam:PassRole 显示 implicitDeny,是因为模拟没有提供 iam:PassedToService 上下文;实际策略允许把任意 myapp-* 角色传给 ECS 任务。结合注册任务定义和更新服务的权限,Agent 就有机会让任意镜像以应用 task role 的身份运行。
直接 API 权限只是入口之一,真正要审的是所有可达路径的并集。
工具自带的 Agent,也要进入同一本账
作者把 Agent 分成两类:自己部署、主动设计角色的 Agent,以及随现有工具进入团队的 Agent。
后者包括 GitHub 的 Dependabot、issue tracker 的摘要功能,以及通过 OAuth 接入邮箱的助手。它们不一定出现在基础设施代码里,却同样拥有身份、授权、网络访问路径和活动记录。
原文甚至提到,这篇文章的选题来自一个定时读取邮箱的 Agent。其 OAuth 连接器能接触的个人数据,比生产账户里的组件还广。仅盯着 AWS 角色,显然会漏掉它。
审计顺序可以沿用作者的四个问题:
- 身份是谁:IAM role、OAuth grant、GitHub App 还是 PAT?谁负责,凭据何时过期?
- 权限是什么:对关键操作运行策略模拟,检查具体资源和条件。
- 能到达哪里:逐项追踪敏感资产经过的 API、环境变量、容器 shell、instance metadata service,以及可能打印秘密的 CI 步骤。
- 活动能否追溯:CloudTrail 中的角色会话是否有明确名称,OAuth 服务商又向用户开放了哪些日志?
作者的邮箱连接器没有提供邮箱所有者可查询的调用痕迹。这是具体连接器的限制,不能推断所有 OAuth 工具都如此。
流水线里的 Agent 也有类似风险。原文称,AWS Continuum for Penetration Testing,原名 AWS Security Agent,于 10 月 5 日进入 public preview,提供部署阶段发现问题、修复后自动重测的能力。原文没有给出年份,也没有列出它要求的权限。
作者担心的是接入位置:他们的 deploy job 经由 CDK bootstrap 链最终拥有 AdministratorAccess。直接把供应商 snippet 放进去,新代码可能通过环境取得部署身份。因此,建议给它独立 job、独立角色,并只提供必要配置。这个案例尚未证明该产品实际需要或读取了部署凭据。
权限要按风险拆,成本要单独管
作者建议保留日常只读观测能力,把生产 shell 和部署操作移到第二个角色,按需通过有人类 MFA 支持的会话承担;或者用 ecs:cluster 条件把 ecs:ExecuteCommand 限制在非生产集群。
这会增加生产排障的步骤,但能让高风险能力不再常驻于 Agent 的日常身份。
另一层措施是 permission boundary,即权限边界。它只限定角色权限上限,不会主动授予权限。作者建议限制 iam:*、Agent 前缀之外的 secretsmanager:*,以及未经人类批准的生产 ECS Exec。审批 session tag 的签发权同样需要约束,否则标签不能证明审批发生过。
成本则是另一笔账。作者的 intelligence service 精确列出了允许调用的模型:
amazon.nova-micro-v1:0、amazon.nova-lite-v1:0、amazon.nova-pro-v1:0、amazon.titan-embed-text-v2:0,以及 us-west-2 的 stability.stable-image-core-v1:1 和 stability.stable-image-ultra-v1:1。
但生成图片的 backend 使用 bedrock:InvokeModel,资源写成 arn:aws:bedrock:*::foundation-model/stability.*,覆盖所有区域的 Stability 模型。
作者解释,Nova Canvas、Titan v2、SDXL 接连进入 Legacy,已经迫使他们三次追着更换 ARN,因此选择通配符减少维护。作者把这项扩大解释为成本暴露,并建议固定 ARN,或者保留通配符、按模型维度设置 budget,同时记录取舍原因。支出检查还应覆盖所有销售模型的 SERVICE 值,不能只看 Amazon Bedrock。
我的判断
这篇最有价值的地方,是用一条实际使用的 ECS Exec 路径,证明了「秘密 API 权限受限」不等于「Agent 无法接触秘密」。单独审每条 policy statement,很容易漏掉权限组合后的效果。
但策略模拟也不是完整的可达性审计。原文自己的 iam:PassRole 结果已经说明,输入缺少条件上下文,输出就可能误导。网络是否连通、容器能否进入、运行身份拿到什么数据,仍需分别核实。
作者建议在 CI 中检测角色是否重新获得对 * 的 ecs:ExecuteCommand、iam:PassRole 或 secretsmanager:GetSecretValue,适合作为权限回归检查,却覆盖不了全部间接路径。
与给 Agent 换一个更克制的模型相比,独立身份和权限边界更直接地约束了它能做什么;代价是角色维护、审批和排障摩擦。原文没有提供改造前后的事故率、成本或效率对照,这部分应视为有案例支撑的工程经验,不能当成量化验证过的收益。
能拿来做什么
- 给代码助手和 SaaS 内置 AI 建一份统一清单,记录负责人、凭据类型、到期方式和可查询日志,别只盘点仓库里定义的角色。
- 对能排查 Node 生产服务的 Agent,沿着 ECS Exec、环境变量和部署权限检查密钥可达性,并把生产 shell、
ssm:StartSession、lambda:UpdateFunctionCode等高风险操作放在人类介入之后。 - 接入流水线 Agent 时,为它建立独立 job 和角色,逐项确认目标 URL、测试凭据及其他输入,避免直接继承 deploy job 的完整环境。
- 把关键权限模拟加入 CI,补齐资源和条件上下文;同时为角色会话命名,让后续能从 CloudTrail 区分 Agent 与人工操作。