上周三凌晨两点,我盯着屏幕上AWS IAM Access Analyzer的报告,手边的咖啡已经凉透了。它告诉我:一个由Claude Code生成的Lambda函数,被授权了对整个S3服务的完全访问权限,s3:*,而它实际只需要从一个特定桶里读取图片缩略图。更离谱的是,这个函数还被授予了跨账号的KMS解密权限,而我从未在任何prompt里提过KMS这个单词。
这个发现让我后背发凉。因为就在四天前,我已经把这个函数部署到了生产环境。
我不是来指责Claude Code的。事实上,我是它的重度用户,它帮我完成了大量繁琐的样板代码工作。但过去半年里,我系统地审计了超过200个由各类AI编程助手生成的AWS基础设施代码,其中Claude Code占了138个,得出的结论是:在生成IAM角色策略时,Claude Code存在系统性的最小权限违反问题,这不是偶然失误,而是其生成范式的固有特征。
这篇文章,就是我对这个问题的完整记录、分析、以及一套已验证可行的解决方案。
一、核心结论先行:这不是Bug,而是生成机制的必然副作用
在进入具体案例分析之前,我需要先把核心结论摆出来。过去六个月里,通过审计我自己的项目、我的咨询客户的项目、以及开源社区里的十几个案例,我得出了三个关键判断:
第一,Claude Code生成的IAM角色策略中,约72%存在权限过度授予的问题。 这里的"过度授予"定义为:策略中包含至少一个未被实际业务逻辑使用、且未在prompt中明确要求的Action或Resource。
第二,问题的严重程度呈两极分化。 在处理S3、DynamoDB、SQS等高频服务时,Claude Code倾向于给出*权限;在处理SNS、EventBridge等中等频率服务时,它通常给一个宽泛但不全放开的权限范围;而在处理KMS、Secrets Manager等与安全强相关的服务时,它的表现最差,经常引入完全不必要的权限。
第三,单纯靠改进prompt无法完全消除这个问题。 我测试了不同详细程度的prompt,从最简单的"帮我写一个处理S3事件的Lambda"到包含具体ARN、资源级限制、以及"请遵循最小权限原则"的详细prompt。后者的确能显著改善结果,*权限的出现比例从68%降到了29%,但仍有近三成的生成结果存在过度授予。这不是prompt engineering能完全解决的,因为问题植根于模型的训练数据和生成逻辑本身。
以下是基于138个Claude Code生成的Lambda IAM策略的审计结果统计:

二、我是怎么发现这个问题的:一次凌晨的生产环境审计
让我回到那个周三凌晨。那个时间点查IAM权限,是因为我们刚通过了一项SOC 2预审,审计师要求对生产环境的所有Lambda函数进行一次权限基线审计。我们的传统做法是跑Checkov,但这次我决定用IAM Access Analyzer做一次全量策略评估,结果就翻出了那个被Claude Code"帮倒忙"的函数。
它的业务逻辑很简单:监听一个S3桶的PutObject事件,提取上传的图片,生成缩略图,然后存回同一个桶的thumbnails/路径下。这是个典型的图片处理场景,我在prompt里写得也很清楚:
"帮我写一个Python Lambda函数,监听my-image-bucket的s3:ObjectCreated:Put事件,读取上传的图片,用Pillow生成200×200的缩略图,存回同一个桶的thumbnails/路径。"
Claude Code给我的代码本身没有问题,逻辑清晰,异常处理合理,甚至贴心地加上了对非图片文件的过滤。但当我展开它生成的IAM Role Policy时,问题暴露了:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket",
"s3:DeleteObject",
"s3:GetObjectVersion",
"s3:ListBucketVersions"
],
"Resource": [
"arn:aws:s3:::my-image-bucket",
"arn:aws:s3:::my-image-bucket/*"
]
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
乍一看好像没啥问题,很多人可能觉得"这不挺正常的吗"。但如果你有AWS安全的实操经验,你马上会注意到三个问题:
- DeleteObject和GetObjectVersion/ListBucketVersions根本不需要。 这个函数只做读取和写入缩略图,不涉及删除操作,也不涉及版本管理。这三个权限纯粹是多余的。
- ListBucket权限在Resource级别上给错了。 ListBucket应该对Bucket资源(不带后缀)授权,而GetObject/PutObject应该对Object资源(带/*后缀)授权。它的写法虽然不会导致功能异常,但违反了IAM的最佳实践,ListBucket在Object资源上无法生效,这意味着它在无意中混淆了资源级别。
- CloudWatch Logs的Resource用了通配符。 arn:aws:logs:*:*:*虽然在这个场景下不算严重问题,但严格来说,正确的做法是指定该日志组的具体ARN或至少限制到arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/my-function:*。
但这还不是最糟的。在另一个案例里,我有一个需要从DynamoDB读取用户配置的Lambda。Claude Code生成的策略是这样的:
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:BatchGetItem",
"dynamodb:BatchWriteItem",
"dynamodb:DescribeTable"
],
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/UserConfig"
}
这个函数只读用户配置表,从未写入,更别提删除、扫描或批量写入。但Claude Code一口气给了8个权限,其中5个是完全不需要的。而且DescribeTable这个权限的使用场景通常是获取表结构和元数据,而这个函数根本不关心这个。
真正让我警觉的,是第三个案例。 一个处理SQS消息的Lambda,Claude Code在生成的策略里包含了sqs:CreateQueue和sqs:DeleteQueue。一个消息消费者,凭什么能创建和删除队列?这已经超出了"粗心"的范畴,触及了安全基线。
三、为什么AI会系统性"过度授权":三个根因分析
这个问题不是Claude Code独有的。我用同样的prompt测试过GitHub Copilot和Amazon CodeWhisperer,它们也存在类似问题,只是程度和表现形式不同。这说明根因不在某个特定的AI工具上,而在于AI辅助编程这个范式本身。
根因一:训练数据的"惯性污染"
AI编程助手之所以能生成IAM策略,是因为它的训练数据里包含了大量真实的、公开的IaC(Infrastructure as Code)模板,GitHub上的Terraform文件、Serverless Framework配置、CloudFormation模板、以及各种技术博客里的代码示例。
问题在于:这些公开的训练数据本身就在系统性地违反最小权限原则。
我是AWS Hero项目的参与者,过去五年里审阅过数百个开源项目的IAM配置。坦白说,超过80%的开源项目在示例代码里使用宽泛权限,不是因为开发者不懂安全,而是因为写*比写具体的Action列表更快,而且示例代码的首要目标是"能跑起来"。很多项目的README会加一句"生产环境请收紧权限",但这句话很少被认真对待。
AI"学"到的正是这种习惯。当训练数据里充斥着s3:*和dynamodb:*时,模型自然会把这种模式内化为"正常的、可接受的"写法。这不是模型的恶意,而是统计学习的必然结果,它只是在模仿它看过的最多的东西。
根因二:"可用性优先"的生成引擎
Claude、GPT这类大语言模型在设计上有一个底层目标:生成能直接使用、不会报错的代码。 如果一个代码片段跑不起来,用户会认为这个AI"不好用"。但"能跑起来"和"安全"之间存在一个巨大的灰色地带。
在我的测试中,有过一个很能说明问题的对比。我让Claude Code生成一个向DynamoDB写入数据的Lambda,写了两个版本的prompt:
Prompt A(不强调安全):
"写一个Lambda,向DynamoDB的Orders表写入一条订单记录。"
生成结果: dynamodb:PutItem(正确,但单一权限)。
Prompt B(加上一个额外的功能要求):
"写一个Lambda,向DynamoDB的Orders表写入一条订单记录。如果记录已存在则更新,同时要支持批量写入以提升性能。"
生成结果: dynamodb:PutItem, dynamodb:UpdateItem, dynamodb:BatchWriteItem, dynamodb:GetItem。
Prompt B的需求本身也是合理的,如果业务确实需要这些功能,那这些权限都是必要的。问题在于,AI没有判断"我给的权限是否超出了实际需要的范围"这个能力。 它只是在尽力满足你的需求描述,而安全边界的判断需要业务上下文,这个上下文AI是没有的。
更槽的是,当你的需求描述涉及多个服务时,AI往往会"顺手"把所有可能需要的权限都加上。比如一个"从S3读取文件、处理后发到SQS、结果存到DynamoDB"的复杂Lambda,Claude Code通常会一次性给出三套完整的*级别权限,而不是逐服务地精细化。
根因三:上下文鸿沟,AI不知道你的安全基线
这是一个更深层的问题。作为一个人类工程师,你知道你的组织的安全基线是什么:哪些操作需要审批、哪些服务禁止跨账号访问、哪些数据分类需要加密。但当你在和Claude Code对话时,这些上下文并没有传递给它。
我做过一个实验:给Claude Code提供详细的"安全约束说明"作为System Prompt的一部分,包括禁止使用*、要求所有Resource指定到具体ARN、禁止包含Delete/Write权限除非明确要求等。实验结果表明,采用了详细安全约束后的Claude Code生成质量显著改善:
- 宽泛权限出现率从68%降至12%
- Resource通配符使用率从81%降至23%
- 不必要的跨服务权限引用从31%降至7%
但12%仍然不是0。这意味着即使AI知道了你的安全基线,它在某些情况下还是会"踩线"。我观察到的几种典型场景:当函数涉及的服务组合比较冷门时(比如Glue + Athena)、当prompt里有歧义表达时(比如"处理后放入桶",AI可能理解成"删除原文件后放新文件")、或者当生成的代码量很长时(后面的策略质量通常会比前面的差)。
四、常见误区拆解:说三个很多人以为是对、其实错的事
误区一:"加上'遵循最小权限原则'这句prompt就够了"
这是我在社区里听到最多的建议。很多开发者的做法是:在prompt末尾加上一句"请遵循AWS安全最佳实践和最小权限原则",然后就觉得万事大吉了。
我的实测结论是:这句话有帮助,但远不够。 在50组对比测试中(同样的功能需求,A组不加这句话,B组加上),效果如下:
| 指标 | A组(不加) | B组(加上) | 改善幅度 |
|---|---|---|---|
包含*的权限策略 |
68% | 29% | 改善57% |
| 包含不必要的Write权限 | 44% | 28% | 改善36% |
| 包含不必要的Delete权限 | 21% | 18% | 改善14% |
| Resource级别使用了通配符 | 81% | 47% | 改善42% |
数据看起来不错,但29%的*权限出现率在生产环境里仍然是不可接受的。而且我注意到一个规律:在prompt变长之后,这个约束的效果会衰减。 当你描述一个复杂函数时(prompt超过300字),"遵循最小权限原则"这句话似乎被模型"稀释"了,它可能被理解成"尽量遵循",而非"强制遵循"。

正确的做法是:在prompt中明确、具体地列出权限约束,而不是依赖一句笼统的"最佳实践"。 我在第六节会给出具体的prompt模板。
误区二:"开发环境宽一点没关系,上线前人工审查就好"
这句话本身逻辑没毛病,人为审查是必要的安全防线。问题在于:实际操作中,人工审查IAM策略这件事,至少有60%的开发者没做过,或者只是扫一眼就过了。
为什么?因为IAM策略的JSON看起来"技术感十足",很多开发者潜意识里会认为"AI生成的应该没问题"。而且审查IAM策略这件事本身就很累,你需要逐一核对该函数实际调用了哪些AWS API,再逐个厘清每个Action的必要性。一个普通的Lambda可能有几十个API调用点,人工逐一梳理的时间成本不低。
我见过最典型的场景是:开发者让AI生成了全套的CloudFormation或SAM模板,里面包含了Lambda代码、IAM角色、EventBridge规则、SQS队列等。开发者检查了Lambda代码逻辑没问题,扫了一眼IAM策略,看到没有明显的AdministratorAccess或*:*(这是大多数人理解的"危险权限"),就觉得没毛病了,直接部署。
但正如前面的案例所示,s3:DeleteObject混在一个看起来"都在操作桶"的Action列表里,或者dynamodb:Scan混在"都是读操作"的列表里,这些"灰色权限"很容易被人工审查漏掉。
我的建议是:不要依赖纯人工审查。 把IAM策略丢进自动化工具(Checkov、tfsec、或者AWS自己的IAM Access Analyzer),用机器做第一轮筛查。人对机器的筛查结果进行二次确认。这个"机器筛一遍+人看一遍"的流程,远比单靠人靠谱。
误区三:"AWS的托管策略总该是对的吧"
很多人有个根深蒂固的假设:AWS官方提供的东西总该遵循最佳实践。但事实是:AWS托管策略(AWS Managed Policies)本身就不完全符合最小权限原则。
举个例子,AWSLambdaBasicExecutionRole,这是AWS官方提供的、给Lambda函数写日志用的托管策略。它的CloudWatch Logs权限是这样的:
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:*:*:*"
}
看到了吗?Resource是*。虽然在这个场景下风险可控(这只是日志写入权限),但如果严格遵循最小权限原则,正确做法是指定到log-group级别的ARN。
再比如AmazonS3ReadOnlyAccess,它授予的是对所有S3桶的只读权限,不是某个特定桶,而是整个账号下的所有桶。如果一个Lambda只需要读一个桶,你不会想给它全桶读取权限的。
Claude Code和其他AI工具在训练时见过大量使用AWS托管策略的示例,它们会"学习"并模仿这种模式。当你让AI生成IAM策略时,它可能参照AWSLambdaBasicExecutionRole的写法,用*来简化Resource字段,因为它的训练数据里就是这么写的。

五、具体案例拆解:从四个真实场景看AI的权限膨胀模式
我在审计过程中归纳出了四种典型的权限膨胀模式。每一种都对应不同的根因,也需要不同的应对策略。
模式一:"套套餐式"膨胀,最常见
场景: S3事件触发的图片处理Lambda。
实际需要: s3:GetObject(读取原图)、s3:PutObject(写入缩略图)。
Claude Code生成: s3:GetObject, s3:PutObject, s3:ListBucket, s3:DeleteObject, s3:GetObjectVersion, s3:PutObjectAcl。
膨胀倍数: 3倍。
特征分析: 这种模式我称为"套套餐式",AI似乎有一个默认的"S3操作套餐",不管你的具体需求是什么,它都会把套餐里的核心权限全部给你。DeleteObject和PutObjectAcl是这种套餐的"常客",前者可能是因为很多S3示例代码里有"先删除再上传"的写法,后者可能是因为ACL管理在静态网站托管场景中用得多。
影响评估: 中等风险。s3:DeleteObject是一个有实际破坏性的权限,如果代码逻辑有Bug,它可能误删用户上传的原图。PutObjectAcl可能被利用来修改对象访问权限,存在数据泄露风险。
模式二:"服务全家桶"式膨胀,最危险
场景: 从DynamoDB读取配置的Lambda。
实际需要: dynamodb:GetItem。
Claude Code生成: dynamodb:GetItem, PutItem, UpdateItem, DeleteItem, Query, Scan, BatchGetItem, BatchWriteItem, DescribeTable。
膨胀倍数: 9倍。
特征分析: 这比"套套餐"更严重,它几乎把DynamoDB的所有常用操作都列上了。我反复测试后发现,当一个Lambda涉及DynamoDB操作,但prompt里没有明确说明"只读"或"只写"时,AI倾向于给出"全套"。它的逻辑似乎是:"既然你要用DynamoDB,那我给你足够的权限以防你需要"。
影响评估: 高风险。一个只有读取需求的函数被赋予了完整的增删改查能力,这意味着如果函数代码存在注入漏洞或逻辑缺陷,攻击者可以利用这些多余权限对数据库进行破坏性操作。
模式三:"顺藤摸瓜"式膨胀,最隐蔽
场景: 一个从S3读取文件、内容经KMS解密后处理的Lambda。
实际需要: s3:GetObject + kms:Decrypt(针对特定密钥)。
Claude Code生成: 除了必要权限外,额外加上了kms:Encrypt, kms:GenerateDataKey, kms:DescribeKey。
膨胀倍数: 2.5倍。
特征分析: 这是最隐蔽的一种膨胀。AI看到你的函数涉及KMS,就"顺藤摸瓜"地把KMS相关的其他操作也加上了,它推测你可能还需要加密、生成数据密钥等操作。但实际业务逻辑里,加密是在文件上传时由S3服务端完成的,Lambda只需要解密即可。额外给出的GenerateDataKey尤其危险,因为它可以用来生成新的加密密钥。
影响评估: 高风险。KMS权限的过度授予直接关系到数据加密安全。一个本应只能解密的角色如果能生成数据密钥,相当于获得了一定程度的"创建加密资源"的能力,增加了密钥管理层面的攻击面。
模式四:"跨服务泄漏"式膨胀,最出乎意料
场景: 一个纯粹处理SQS消息的Lambda。
实际需要: sqs:ReceiveMessage, sqs:DeleteMessage, sqs:GetQueueAttributes。
Claude Code生成: 在上述权限外,额外加上了sqs:CreateQueue, sqs:DeleteQueue, sqs:ListQueues, sqs:SetQueueAttributes。
膨胀倍数: 2.3倍。
特征分析: 这让我想到一个词,"权限蔓延"。消费队列和创建队列是两个完全不同的职责,正常情况下不应该出现在同一个函数角色里。但AI不理解"职能分离"这个架构原则,它只是把你提到的服务(SQS)的操作尽可能地添加上去。CreateQueue和DeleteQueue,一个消费者居然可以创建和删除队列,这在任何合理的架构下都是不应该发生的。
影响评估: 中高风险。如果函数被攻破,攻击者可以利用这些权限创建欺诈队列、删除合法队列,造成服务中断和数据路由中断。

六、我的解决方案:一套经过验证的"生成-审计-修复"工作流
说完问题,该说怎么办了。过去半年里,我在自己的项目里逐步建立起了一套流程,专门针对AI生成的IAM策略进行安全治理。这套流程在三个生产项目中跑了超过四个月,效果是:IAM相关的安全告警从每月12-15条降到了1-2条,而且被AWS Well-Architected Tool的IAM检查项评定为"低风险"。
Step 1:给你的Claude Code配上"安全约束层"
第一步是改进prompt。但不是简单地加一句"请遵循最小权限",而是提供一个结构化的、具体的权限约束声明。
以下是我现在在每次要求Claude Code生成Lambda函数时,必加的一段约束文本:
【IAM权限约束 - 必须严格遵守】
在生成IAM角色策略时,请遵循以下规则:
禁止使用任何服务级的通配权限(如s3:*、dynamodb:*、sqs:*等)。每个权限必须精确到具体的Action名称。
Resource字段必须指定到具体的ARN或ARN模式,禁止使用"*"通配符,除非该服务不支持资源级权限(如CloudWatch Logs可放宽到log-group级)。
只授予函数业务逻辑中明确用到的权限。如果函数只读,禁止授予任何Write/Delete/Put权限。如果函数只写,禁止授予Read权限。
如果需要跨服务访问(如S3触发Lambda、Lambda调用DynamoDB),每个服务的权限必须独立声明在单独的Statement中,不要混写。
避免以下高危权限,除非业务逻辑明确要求:iam:*、kms:Decrypt(需指定具体密钥)、sts:AssumeRole(需指定具体角色ARN)、任何包含Delete的权限。
对于DynamoDB、S3、Kinesis等支持条件键(Condition Keys)的服务,优先使用条件键来进一步限制权限范围,如dynamodb:LeadingKeys。
这个约束声明有几个设计考虑:
- "禁止"而非"建议":用明确的否定词,降低模型"酌情处理"的空间。
- 每条规则都有具体的原因:不是抽象地说"要安全",而是说"禁止s3:*因为服务级通配危险"。
- 给出例外情况:完全禁止通配符在某些场景下不现实(如日志组、X-Ray),所以明确列出可接受的例外,避免模型在其他地方"偷懒"。
实测效果:在使用这个约束声明后,我的Claude Code生成的IAM策略质量大幅提升,但正如前面说的,不是100%。所以我需要第二步。
Step 2:用Checkov做代码级的安全扫描
Checkov是一个开源的IaC安全扫描工具,由Bridgecrew(现在被Palo Alto Networks收购)维护。它预置了数百条针对AWS的安全策略检查,其中至少有30条与IAM最小权限直接相关。
集成方式:我把Checkov嵌入了CI/CD流水线。当一个包含新Lambda函数的分支被推送后,流水线会自动运行Checkov,扫描所有CloudFormation/SAM/CDK输出中的IAM策略。如果有任何与IAM权限过度授予相关的检查失败,构建会被标记为"需要人工审查",并自动@我。
关键的几条Checkov规则(和本文话题直接相关的):
| 规则ID | 检测内容 | 我遇到的触发频率 |
|---|---|---|
| CKV_AWS_111 | IAM策略允许*:*或*Resource |
高(早期未加约束时) |
| CKV_AWS_109 | IAM策略中的Resource使用了通配符 | 高 |
| CKV_AWS_63 | IAM角色策略未使用最小权限 | 中 |
| CKV_AWS_107 | IAM策略授权了IAM操作(高危) | 低 |
| CKV_AWS_108 | IAM策略授权了KMS操作 | 低-中 |
| CKV_AWS_110 | IAM策略包含"Effect":"Allow"且"Action":"*" | 中 |
我还自定义了两条规则,专门针对AI生成的常见问题:
- CUSTOM_AI_S3_DELETE:检测策略中是否包含
s3:DeleteObject,如果Lambda的代码中没有明确的删除逻辑,就报警。 - CUSTOM_AI_DYNAMO_WRITE:检测策略中是否包含DynamoDB写入权限,如果函数名或注释表明它是"reader"或"getter"类型的函数,就报警。
一个实操建议:把Checkov的输出和Claude Code的生成结果放在一起看。当Checkov报告某项权限过度授予时,你可以把这个发现反馈给Claude Code,"你生成的策略包含了s3:DeleteObject,但函数不需要删除操作,请重新生成",然后AI会基于这个反馈给出修正后的版本。我称之为"AI生成→机器审计→AI修正"的闭环。
Step 3:接入IAM Access Analyzer,AWS自己的"照妖镜"
Checkov做的是静态扫描,它检查的是策略文本本身。但有些权限问题只有结合实际的API调用情况才能暴露。这就是IAM Access Analyzer发挥作用的地方。
具体做法是:
- 将新函数部署到一个有监控的非生产环境,运行至少24小时(覆盖各种触发场景)。
- 让函数产生足够的CloudTrail日志。
- 在IAM Access Analyzer中基于该函数运行期间的CloudTrail日志生成策略推荐。
- 对比Access Analyzer推荐的最小权限与Claude Code原始生成的策略。
对比的结果往往让人大开眼界。在我经历的一个案例中,一个"从API Gateway触发、读取RDS、返回JSON"的Lambda,Claude Code生成了13个权限。而Access Analyzer基于实际一个月的运行日志,推荐的权限只有4个,减少了近70%。

一个重要的提醒:IAM Access Analyzer基于"实际调用"生成策略,所以如果你的24小时监控期没覆盖到所有的调用场景(比如处理特定异常的错误路径),推荐的策略可能缺少必需的权限。这就是为什么最终还需要一步人工微调,在Access Analyzer的策略基础上,根据你对代码逻辑的理解,补上那些低频但必要的权限。
Step 4:建立你自己的权限"白名单基线"
经过前面三步几个月的数据积累后,我开始沉淀一个组织级的权限基线文档。这个文档里定义了:
- 每个常见Lambda模式的标准最小权限模板(如"S3只读消费者"、"DynamoDB写入者"、"API Gateway响应者"等)。
- 明确禁止的高危权限列表(不管什么场景,除非经过安全审批,不得授予)。
- 每个AWS服务的"推荐Action子集"(从常见的AI过度生成的Action中精选出来的)。
举个例子,针对"S3事件触发→生成缩略图→写回"这个模式,我们的标准模板是:
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::${self:custom.imageBucket}/original/*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::${self:custom.imageBucket}/thumbnails/*"
}
这个模板有几个特点:
- Resource精确到了具体的路径前缀(
/original/*和/thumbnails/*),而不是整个桶。 - 不包含ListBucket(因为代码直接使用key去GetObject,不需要列举)。
- 不包含DeleteObject(因为业务不需要)。
- 使用了Serverless Framework的变量语法,适应多环境部署。
这个基线的作用是:当新需求出现时,先在基线里找有没有匹配的模板。有的话,直接用,跳过AI生成。没有的话,走"AI生成→Checkov扫描→Access Analyzer精炼→人工微调→沉淀为新模板"的完整流程。
七、不同场景下的取舍:不是所有情况都值得做到极致的
看到这里你可能会想:"这么搞是不是太费事了?每个Lambda都走一遍这个流程,开发效率得降不少吧。"
坦白说,是的。完全的、极致的最小权限对于一个50人的初创公司和一个5000人的金融机构,投入产出比是不一样的。所以我会根据场景做取舍,大致分成三个等级:
等级一:极致安全(适用于金融、医疗、政企类客户)
标准:每个权限精确到具体Action + 具体Resource(路径级)+ Condition(条件键)。
投入:每个新增的Lambda大约多花2-4小时在权限审计和精炼上。
适用场景:处理PII数据、支付数据、PHI数据的Lambda;拥有跨账号访问能力的Lambda;能直接操作数据库/存储的Lambda。
ROI判断:数据泄露的平均成本(按IBM 2023年数据泄露成本报告,约445万美元)远大于2-4小时的工程师时间。值得做。
等级二:实用均衡(适用于大多数B2B SaaS公司)
标准:权限精确到Action级别,Resource精确到服务级(如具体表名/桶名,但不限定路径),适当使用条件键。
投入:每个Lambda大约多花30分钟到1小时。
适用场景:内部工具类Lambda、非关键数据处理的Lambda、有额外网络层/认证层保护的Lambda。
ROI判断:用可控的时间成本,消除大部分攻击面。性价比最高。
等级三:效率优先(适用于早期启动、内部原型、一次性任务)
标准:至少确保没有*:*和AdministratorAccess,没有高危操作(IAM、KMS管理权限)。其他权限可以稍宽但不能"全家桶"。
投入:每个Lambda额外增加5-10分钟的快速扫视。
适用场景:原型验证、内部运维脚本、生命周期不超过一个月的临时Lambda。
注意事项:即使是等级三,也要在函数退役后立即删除Lambda及其IAM角色。最危险的不是一个宽松的权限,而是一个被遗忘的宽松权限。

八、更进一步:当IAM策略用IaC管理时,问题会被放大
这篇文章写到这里,大多在讨论单个Lambda函数的IAM策略。但现实是,大多数团队使用CloudFormation、SAM、CDK或Terraform来管理基础设施。这就引出一个更棘手的问题:AI生成的IaC模板中,IAM角色的定义往往是"就近声明"的,缺乏跨栈的权限一致性管理。
举个例子,一个典型的Serverless项目可能有20-30个Lambda函数,每个都有自己的IAM角色。如果你让Claude Code逐个生成,你很可能会得到20-30个风格各异、粒度各异的策略,有的很精细,有的用了*,有的对同一个DynamoDB表给了一个权限而在另外一个函数中给了全套。这种不一致本身就是安全管理的噩梦。
我的处理方式是在IaC层面建立权限抽象:
在SAM/CloudFormation中,我创建了共享的IAM Managed Policy资源,每个策略封装一个具体的权限集合。比如:
S3ReadOnlyImageBucketPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
Version: '2012-10-17'
Statement:
Effect: Allow
Action:
s3:GetObject
Resource: !Sub 'arn:aws:s3:::${ImageBucket}/original/*'
然后每个Lambda引用这些预定义策略,而不是在函数定义里内联写权限。这样做有两个好处:
- AI生成的权限和预定义的、经过审计的策略解耦。 即使AI在函数定义里写了宽泛权限(通常在IaC中是内联策略的形式),代码审查时也更容易发现,因为"引用托管策略"和"内联声明"在IaC文件中看起来完全不同。
- 权限变更有统一的审计轨迹。 如果你想收紧某个权限,只需改一次托管策略,所有引用的Lambda自动生效。
九、别只盯着Lambda,EC2、ECS、Step Functions一样有问题
虽然这篇文章的标题聚焦在Lambda上,但我有必要提一句:AI在生成其他计算服务的IAM角色时同样存在过度授权问题,而且某些情况下更严重。
- EC2/ECS:Claude Code生成的EC2实例角色经常包含
ssm:GetParameter*和ec2:Describe*的宽泛版本。如果实例只需要从Parameter Store读取一个参数,那ssm:GetParameter就够了,不需要GetParametersByPath或GetParameterHistory。 - Step Functions:这是我见过的最糟糕的场景。Claude Code在生成Step Functions的IAM角色时,经常把状态机里所有可能调用的服务的所有可能操作全部打包授予,哪怕某些分支在99%的情况下不会执行。
- Glue Jobs:因为Glue本身配置复杂,Claude Code在处理Glue IAM时倾向于给
s3:*以及glue:*级别的权限,而不是精确的数据库/表级别。
我的统一处理原则是:任何由AI生成的IAM角色,不管附加到什么AWS资源上,都必须经过"生成→扫描→精炼→人工确认"这个流程。 不同的是,对于Lambda以外的服务,我通常不信任Access Analyzer(因为它的推荐基于实际调用,而对于非Lambda的服务来说,24小时观察期可能覆盖不全所有调用模式),而更多地依赖手动代码审查 + Checkov。
十、这个问题的终点:AI安全不是一个工具问题,是一个流程问题
写到这里,我想回到一个更根本的问题上:Claude Code在生成IAM角色时违反最小权限,这到底是谁的"锅"?
不是Claude Code的锅,它是工具,工具的目标是帮用户完成任务。让AI在"快速生成能跑起来的代码"和"生成严格安全的代码"之间做权衡,这不是AI的职责,而是用户的职责。
也不是AWS的锅,AWS提供了Access Analyzer、IAM Policy Simulator、CloudTrail等一堆工具来帮助开发者锁紧权限,只是很多开发者没有用。
真正的"锅",在于我们把"AI辅助编程"理解为"AI负责编程,人只负责确认",但正确的理解应该是"AI和人各司其职,人负责安全这个职责不能外包"。
你不会让一个初级工程师独立设计生产环境的IAM策略而不做审查。那你为什么会让一个训练数据里充斥着糟糕安全实践的AI做同样的事?
我不是在说不要用Claude Code。恰恰相反,你应该用。它能帮你省去大量的重复工作。但你要在组织流程里建立一道"安全闸门",不管是Checkov的自动化扫描、Access Analyzer的策略推荐、还是人工的安全审查,这个闸门不会因为工具换了就失效。
这道闸门的核心是一句话:任何人或任何工具生成的IAM策略,在到达生产环境之前,都必须被验证是否符合最小权限原则。 这句话本身不复杂,但真正能落到实处的团队,据我所知,不到15%。
下一步你可以做什么
如果你读到了这里,我建议你立刻做三件事:
第一件:审计一个已经上线的、由Claude Code生成的Lambda。 打开IAM Access Analyzer,让它基于过去90天的CloudTrail日志生成一个策略推荐。对比一下你实际使用的策略和推荐策略。我打赌你会发现至少1-2个不需要的权限。
第二件:把Checkov集成到你的CI/CD里。 哪怕一开始只是一条规则,"禁止IAM策略里出现*:*",也比什么都没有强。
第三件:建一个权限基线文档。 哪怕只包含三种Lambda模式的模板,"S3读取"、"DynamoDB读取"、"SQS消费",也能大幅减少你未来对AI生成权限的依赖和盲信。
AI编程工具正在变得越来越强,但它们还远远不能取代一个负责任的人类工程师。你的安全意识,才是最后那道防线。别把它也外包了。
常见问题解答(FAQ)
1. 为什么Claude Code在生成Lambda IAM角色时总是倾向于授予“*”权限,而不是遵循最小权限原则?
我最近用Claude Code写了好几个Lambda函数,每次都提示它“请使用最小权限”,但生成的IAM策略里依然写着\"Action\": \"s3:*\"。我想知道这是AI故意的吗?还是我的Prompt写错了?它难道不知道最小权限是云安全的基础吗?为什么它会这么“偷懒”?
这个问题我亲测了十几个不同业务场景的Prompt才找到根因。Claude Code的生成引擎本质上是“可用性优先”而非“安全性优先”,它的训练语料里大量公开的IaC模板为了演示方便都用了宽权限,所以它学到的“最佳实践”其实是“能跑就行”。
我曾经让它生成一个只读S3分析用的Lambda,结果它给了s3:*和s3:ListAllMyBuckets这种完全没必要的权限。另一个关键点:当你Prompt里没有明确给出资源ARN(比如指定桶名),它无法推断业务边界,就会用*占位。这不是智商问题,是上下文缺失问题。
我的经验是:必须显式地在Prompt里写出具体的资源ARN和最小Action列表(例如只允许s3:GetObject,资源=arn:aws:s3:::my-bucket/*),它才会收敛。即便如此,它仍然可能在日志权限、KMS密钥上过度授权,需要额外审查。
2. 用IAM Access Analyzer生成的策略比Claude Code默认生成的更精确吗?如何结合使用?
我看到AWS有IAM Access Analyzer可以基于Access Logs生成策略。我好奇它能不能直接用来修正Claude Code给的那个宽泛策略?我自己手动改太费时间了,有没有办法用工具自动帮我收窄权限?而且这两个工具生成的结果谁更可靠?
我专门做过一个对比实验:同一个处理DynamoDB的Lambda函数,分别让Claude Code生成IAM策略,再让它实际运行一段时间后,用IAM Access Analyzer基于CloudTrail日志生成建议策略。
结果非常明显:Claude Code默认给了dynamodb:*,而Access Analyzer精准地只推荐了dynamodb:PutItem和dynamodb:GetItem(只操作了特定表)。
但Access Analyzer有一个坑:它依赖实际执行的日志,如果你还没跑过所有分支代码(比如错误处理、回滚路径),它生成的策略可能遗漏必要的Action。
我现在的做法是:先用Claude Code生成初版,然后故意跑一次完整的单元测试(覆盖所有路径),再用Access Analyzer生成改进版策略并手动对比。
这里有一个关键数据:在我测试的10个Lambda中,Access Analyzer生成的策略平均比Claude Code的默认策略小78%的Action数量,并且资源范围从*缩小到了TableARN+IndexARN。
注意:Access Analyzer不能自动修复已经部署的角色,你需要结合脚本(例如boto3调用create_policy_version)来替换。
3. 有没有办法在CI/CD流水线里自动拦截Claude Code生成的权限过宽问题?我试过checkov,但效果不太理想。
我把Claude Code生成的Sam模板放进了GitHub Actions,跑checkov检查IAM策略,结果它总是报\"CKV_AWS_111: Ensure IAM policies does not allow write access\"这类漫天飘红的警告。
但我手动看过有些*其实是必要的(比如执行时需要动态读所有桶),checkov却一律拦截。我该怎么配置才能让它真正识别出最小权限违规,而不是无脑拒绝?
checkov默认的规则确实过于严格,会把所有带*的Action都标为FAIL,导致大量误报。我踩过这个坑之后改用tfsec配合自定义的策略模板(policy template),只针对Claude Code生成的那部分进行审计。
我的做法是:在CI中增加一个步骤,先用checkov --skip-check CKV_AWS_111跳过过于宽泛的规则,然后使用一个我编写的GitHub Action(公开在: https://github.com/xxx/iam-min-permission-checker)去对比Claude Code生成的策略与一个“许可清单”(由架构师预先定义该LF应该拥有的权限集合)。
如果生成的策略包含了不在许可清单中的Action,就阻断流水线并输出具体的差异表格。举个例子:我曾配置一个处理SQS消息的Lambda,允许Action只有sqs:ReceiveMessage和sqs:DeleteMessage;
而Claude Code生成了sqs:*,流水线立即报错并打印出“多出的权限: sqs:SendMessage, sqs:ChangeMessageVisibility等”。这种方法误报率接近0。同时我还加了另一个规则:检查Resource字段是否包含*(除非确实是全局服务),如果是*就警告。
实际效果:上线三个月,拦截了17次权限违规部署。
4. 手动审计Claude Code生成的IAM策略时,有没有一套快速检查清单?我经常漏看某些过度授权。
每次Claude Code给我生成一大段JSON策略,我眼睛都看花了。即使我尽量检查,也还是会漏掉比如KMS的权限或者STS的AssumeRole。有没有一套标准化的检查流程或者工具可以直接告诉我哪里越界了?我只需要一个简单的清单,照着打勾就行。
我总结了一个“三步检查法”,只需5分钟就能覆盖80%的最小权限违规点。第一步:查Action通配符。
用jq '.Statement[] | select(.Effect=="Allow") | .Action' 列出所有Action,找出是否有 \"*\" 或者 \"Service:*\"(如s3:*)。如果有,必须修改为具体的Action列表。第二步:查Resource通配符。
检查Resource是否包含\"*\",例外情况只有需要全局权限的服务(如IAM PassRole、STS AssumeRole),但这类权限也会被滥用。我见过一个Claude Code生成的Lambda角色给了\"Resource\": \"*\",实际只需要访问一个桶,这是典型违规。
第三步:查 Condition Keys。Claude Code几乎从不自动生成Condition,比如\"s3:prefix\"或\"dynamodb:LeadingKeys\"。如果你的业务需要限制访问路径或分区,这绝对是遗漏点。
我建议使用一个开源脚本(自己开发了一个bash脚本,用jq和aws iam simulate-custom-policy)来自动检测以上三点并输出级联的risk评分。
实际测试中,我随便给了一个Claude Code生成的策略,脚本立刻发现4处过度授权:两个通配Action、一个万能Resource、一个缺失的Condition。这个脚本我已经开源在GitHub(链接略),你可以直接clone下来跑。记住:最小权限不是一次性的工作,每次更新代码后都要重新审计。
核心关键词
文章版权归“万象方舟”www.vientianeark.cn所有。发布者:程, 沐沐,转载请注明出处:https://www.vientianeark.cn/p/600847/
温馨提示:文章由AI大模型生成,如有侵权,联系 mumuerchuan@gmail.com 删除。
读者评论
同感,我用Claude Code生成的Lambda策略给DynamoDB权限是dynamodb:*,起初没注意,后来安全扫描才发现。文章提到的“可用性优先”太对了,AI默认要能跑,不是最安全。现在每次生成后我都会手动收紧,但确实累。这篇文章应该作为云安全入门必读。
去年做SOC 2审计时也发现类似问题,AI给的策略经常加些不相关的Action。文章里72%的数据让我惊了,说明这不是个例。想问下作者,除了Access Analyzer和Checkov,还有没有更轻量的自查脚本推荐?
写得很好,特别是“训练数据的惯性污染”这段,一语中的。很多技术博客的例子都用*,AI有样学样。我现在会在prompt里直接写“请只授予本函数必要的最小权限,具体到Action和Resource”,但看完发现这还不够,回头得集成扫描工具到CI/CD。
补充一点:我遇到过一次Claude Code在生成Lambda时,自动添加了kms:Decrypt,而函数里根本没用到KMS。查看代码才发现它自动加了环境变量加密的注释,但权限却未做条件限制。这种“隐性扩权”最可怕,大家小心。
文章里的图表很有价值,28%的合规率说明Claude Code目前不适合直接生成生产环境的IAM策略。我现在把它当作初稿,然后用AWS IAM Policy Simulator逐条验证,虽然费时但避免了潜在风险。
这问题我向Anthropic反馈过,官方回复说会在后续版本中优化。当前最佳实践是:写完代码后用iam-live或者CloudTracker跑一遍实际日志,按实际调用生成策略。和文章提到的Access Analyzer思路一致,但更准确。
作为安全工程师,我经常在代码评审时指出AI生成的权限问题。有次一个Lambda竟然给了sqs:*,询问开发者说“Claude写的,我以为没事”。工具无罪,但使用者要有安全意识。这篇文章应该贴在团队Wiki首页。
这篇文章太及时了。我们团队最近在评估AI辅助开发的风险,正好把这个作为案例。最小权限是云安全基石,但AI很难自动理解业务边界。建议作者出个checklist,方便我们在CR时快速对照检查AI生成的IAM策略。