fix(iam): accept bare "*" resource in PutUserPolicy (#9209) (#9210)

AWS IAM treats a bare "*" in a statement's Resource as "any resource",
but the embedded IAM resource parser required a 6-segment S3 ARN and
silently skipped anything else. With a policy like
{Action: "s3:*", Resource: "*"}, every resource was dropped and the
statement produced no actions, so PutUserPolicy rejected the document
with "no valid actions found in policy document".

Short-circuit Resource == "*" to the same full-wildcard path that
"arn:aws:s3:::*" already takes.
This commit is contained in:
Chris Lu authored and GitHub committed 2026-04-23 22:14:41 -07:00
1 parent da2e90aefd
commit 88c2f3c34d
2 files changed
+39 -4

No files matched your search

+12 -4
View File
@@ -819,9 +819,18 @@ func (e *EmbeddedIamApi) getActions(policy *policy_engine.PolicyDocument) ([]str
return nil, fmt.Errorf("not a valid effect: '%s'. Only 'Allow' is possible", statement.Effect)
}
for _, resource := range statement.Resource.Strings() {
res := strings.Split(resource, ":")
if len(res) != 6 || res[0] != "arn" || res[1] != "aws" || res[2] != "s3" {
continue
// AWS IAM treats a bare "*" as "any resource". Normalize it to the
// full-wildcard S3 ARN so it flows through the same path as
// "arn:aws:s3:::*" instead of being dropped as malformed.
var resourcePath string
if resource == "*" {
resourcePath = "*"
} else {
res := strings.Split(resource, ":")
if len(res) != 6 || res[0] != "arn" || res[1] != "aws" || res[2] != "s3" {
continue
}
resourcePath = res[5]
}
for _, action := range statement.Action.Strings() {
act := strings.Split(action, ":")
@@ -833,7 +842,6 @@ func (e *EmbeddedIamApi) getActions(policy *policy_engine.PolicyDocument) ([]str
return nil, fmt.Errorf("not a valid action: '%s'", act[1])
}
resourcePath := res[5]
if resourcePath == "*" {
// Wildcard - applies to all buckets
actions = append(actions, statementAction)