Fix the least-privilege check on an IAM policy

Review the AI's codeEasy10 minAmazon style

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, so s3:* does not match s3control: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_actions exactly.
  • Return every action in catalog that 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
Inputexcess_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
Inputexcess_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[]