Fix the least-privilege check on an IAM policy
Your task
You asked an assistant to let a Lambda decrypt with one KMS key and read one S3 bucket. It granted kms:* and s3:* on every resource, which includes deleting keys and rewriting bucket policies. The Lambda works, so nothing at runtime shows the extra power. The security team now expands each policy against a list of real actions to see what it allows.
An assistant wrote excess_allowed_actions(granted_patterns, catalog, needed_actions). It is in the editor. It has a bug. Find it and fix it.
Input and output:
granted_patterns: the policy's Action entries, such as"kms:*"or"s3:GetObject". The list can be empty.catalog: the real API actions to check, each"service:Name", such as"kms:Decrypt". It can repeat an action.needed_actions: the actions the role was asked to have.- Return the actions the role can call but was never asked for, as a list of strings.
Rules the tests check:
- A pattern that is exactly
*matches every action. - A pattern that ends with
*matches every action that starts with the rest of the pattern, the text before that last*. The colon is part of that text, sos3:*does not matchs3control:GetBucket. - Any other pattern matches only the action equal to it. A
*anywhere but the end is a plain character. - All matching is case sensitive.
- An action is allowed when at least one pattern matches it. It is needed when it equals one of
needed_actionsexactly. - Return every action in
catalogthat is allowed and not needed, in catalog order. Report each action once, even when the catalog repeats it.
Examples
excess_allowed_actions(granted_patterns: list[str], catalog: list[str], needed_actions: list[str]) -> list[str]Example 1
Input
excess_allowed_actions(["kms:*", "s3:*"], ["kms:Decrypt", "kms:Encrypt", "kms:ScheduleKeyDeletion", "kms:PutKeyPolicy", "s3:GetObject", "s3:ListBucket", "s3:DeleteObject", "s3:PutBucketPolicy"], ["kms:Decrypt", "s3:GetObject", "s3:ListBucket"])Output
["kms:Encrypt", "kms:ScheduleKeyDeletion", "kms:PutKeyPolicy", "s3:DeleteObject", "s3:PutBucketPolicy"]Example 2
Input
excess_allowed_actions(["kms:Decrypt", "s3:GetObject", "s3:ListBucket"], ["kms:Decrypt", "kms:Encrypt", "kms:ScheduleKeyDeletion", "kms:PutKeyPolicy", "s3:GetObject", "s3:ListBucket", "s3:DeleteObject", "s3:PutBucketPolicy"], ["kms:Decrypt", "s3:GetObject", "s3:ListBucket"])Output
[]