iam-policy-validator 1.15.6__tar.gz → 1.16.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/ci.yml +4 -4
  2. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/pre-release.yml +1 -1
  3. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/release.yml +1 -1
  4. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/CHANGELOG.md +19 -0
  5. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/PKG-INFO +1 -1
  6. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/action.yaml +3 -3
  7. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/__version__.py +1 -1
  8. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/__init__.py +2 -0
  9. iam_policy_validator-1.16.0/iam_validator/checks/condition_key_validation.py +125 -0
  10. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/condition_type_mismatch.py +20 -0
  11. iam_policy_validator-1.16.0/iam_validator/checks/ifexists_condition_check.py +210 -0
  12. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/set_operator_validation.py +20 -6
  13. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/check_registry.py +1 -0
  14. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/condition_validators.py +77 -3
  15. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_condition_key_validation_check.py +133 -0
  16. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_condition_type_mismatch.py +69 -0
  17. iam_policy_validator-1.16.0/tests/checks/test_ifexists_condition_check.py +342 -0
  18. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_set_operator_validation.py +77 -0
  19. iam_policy_validator-1.15.6/iam_validator/checks/condition_key_validation.py +0 -88
  20. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/dependabot.yml +0 -0
  21. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/cleanup-prereleases.yml +0 -0
  22. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/codeql.yml +0 -0
  23. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/docs.yml +0 -0
  24. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/scorecard.yml +0 -0
  25. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.gitignore +0 -0
  26. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/CONTRIBUTING.md +0 -0
  27. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/LICENSE +0 -0
  28. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/Makefile +0 -0
  29. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/README.md +0 -0
  30. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/SECURITY.md +0 -0
  31. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/api-reference/checks.md +0 -0
  32. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/api-reference/exceptions.md +0 -0
  33. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/api-reference/index.md +0 -0
  34. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/api-reference/models.md +0 -0
  35. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/api-reference/sdk.md +0 -0
  36. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/changelog.md +0 -0
  37. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/contributing/development-setup.md +0 -0
  38. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/contributing/index.md +0 -0
  39. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/contributing/releasing.md +0 -0
  40. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/contributing/testing.md +0 -0
  41. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/architecture.md +0 -0
  42. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/custom-checks/best-practices.md +0 -0
  43. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/custom-checks/examples.md +0 -0
  44. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/custom-checks/index.md +0 -0
  45. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/custom-checks/tutorial.md +0 -0
  46. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/index.md +0 -0
  47. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/sdk/advanced.md +0 -0
  48. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/sdk/index.md +0 -0
  49. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/sdk/policy-utilities.md +0 -0
  50. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/sdk/quickstart.md +0 -0
  51. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/sdk/validation.md +0 -0
  52. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/getting-started/first-validation.md +0 -0
  53. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/getting-started/index.md +0 -0
  54. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/getting-started/installation.md +0 -0
  55. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/getting-started/quickstart.md +0 -0
  56. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/includes/abbreviations.md +0 -0
  57. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/index.md +0 -0
  58. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/integrations/github-actions.md +0 -0
  59. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/integrations/gitlab-ci.md +0 -0
  60. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/integrations/index.md +0 -0
  61. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/integrations/mcp-server.md +0 -0
  62. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/integrations/pre-commit.md +0 -0
  63. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/stylesheets/extra.css +0 -0
  64. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/checks/advanced-checks.md +0 -0
  65. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/checks/aws-validation.md +0 -0
  66. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/checks/index.md +0 -0
  67. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/checks/security-checks.md +0 -0
  68. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/cli-reference.md +0 -0
  69. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/configuration.md +0 -0
  70. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/index.md +0 -0
  71. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/output-formats.md +0 -0
  72. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/troubleshooting.md +0 -0
  73. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/README.md +0 -0
  74. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/access-analyzer/example1.json +0 -0
  75. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/access-analyzer/example2.json +0 -0
  76. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/aws-service-definitions/iam.json +0 -0
  77. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/aws-service-definitions/s3.json +0 -0
  78. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/full-reference-config.yaml +0 -0
  79. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/github-labels-config.yaml +0 -0
  80. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/minimal-validation-config.yaml +0 -0
  81. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/offline-validation.yaml +0 -0
  82. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/policy-level-condition-enforcement-config.yaml +0 -0
  83. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/strict-security.yaml +0 -0
  84. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/custom_checks/cross_account_external_id_check.py +0 -0
  85. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/custom_checks/domain_restriction_check.py +0 -0
  86. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/access-analyzer-only.yaml +0 -0
  87. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/basic-validation.yaml +0 -0
  88. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/custom-policy-checks.yaml +0 -0
  89. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/multi-region-validation.yaml +0 -0
  90. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/resource-policy-validation.yaml +0 -0
  91. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/sarif-code-scanning.yaml +0 -0
  92. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/sequential-validation.yaml +0 -0
  93. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/two-step-validation.yaml +0 -0
  94. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/validate-changed-files.yaml +0 -0
  95. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/allowed-wildcard-resource.json +0 -0
  96. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/api_gateway_management.json +0 -0
  97. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/athena_query_access.json +0 -0
  98. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/backup_vault_access.json +0 -0
  99. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/cloudformation_deployer.json +0 -0
  100. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/cloudwatch_monitoring.json +0 -0
  101. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/cognito_user_pool.json +0 -0
  102. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/dynamodb_table_access.json +0 -0
  103. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/ecs_task_execution.json +0 -0
  104. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/eventbridge_rules.json +0 -0
  105. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/glue_etl_jobs.json +0 -0
  106. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/insecure_policy.json +0 -0
  107. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/insecure_policy.yaml +0 -0
  108. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/invalid-resource-constraint.json +0 -0
  109. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/invalid-sid-special-chars.json +0 -0
  110. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/invalid-sid-with-spaces.json +0 -0
  111. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/invalid_policy.json +0 -0
  112. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/kms_encryption_keys.json +0 -0
  113. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/lambda_developer.json +0 -0
  114. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/lambda_developer.yaml +0 -0
  115. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/maximum_size_policy.json +0 -0
  116. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/policy_missing_required_tags.json +0 -0
  117. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/policy_tag_enforcement_example.json +0 -0
  118. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/policy_with_wildcard_resources.json +0 -0
  119. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/privilege_escalation_scattered.json +0 -0
  120. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/rds_database_admin.json +0 -0
  121. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/s3_bucket_access.yaml +0 -0
  122. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/sample_policy.json +0 -0
  123. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/sample_policy.yaml +0 -0
  124. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/secrets_manager_access.json +0 -0
  125. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/sensitive-action-wildcards.json +0 -0
  126. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/sns_sqs_messaging.json +0 -0
  127. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/step_functions_workflow.json +0 -0
  128. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/terraform-template-policy.json +0 -0
  129. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/test_none_of_valid.json +0 -0
  130. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/test_none_of_violations.json +0 -0
  131. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/valid-sid-formats.json +0 -0
  132. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/wildcard_examples.json +0 -0
  133. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/wildcard_examples.yaml +0 -0
  134. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/wrong-condition-key.json +0 -0
  135. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/wrong-s3-condition.json +0 -0
  136. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-invalid-allow-effect.json +0 -0
  137. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-invalid-not-action.json +0 -0
  138. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-invalid-specific-principal.json +0 -0
  139. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-invalid-unsupported-service.json +0 -0
  140. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-invalid-wildcard-action.json +0 -0
  141. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-valid-enforce-encryption.json +0 -0
  142. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/backup-vault-policy-org-access.json +0 -0
  143. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/ecr-repository-policy-org-restricted.json +0 -0
  144. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/ecr-repository-policy-public.json +0 -0
  145. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/efs-filesystem-policy-vpc-only.json +0 -0
  146. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/glacier-vault-policy-cross-account.json +0 -0
  147. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/kms-key-policy-cross-account.json +0 -0
  148. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/kms-key-policy-insecure.json +0 -0
  149. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/kms-key-policy-org-restricted.json +0 -0
  150. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/kms-key-policy-service-specific.json +0 -0
  151. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/lambda-permission-api-gateway.json +0 -0
  152. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/lambda-permission-cross-account-invoke.json +0 -0
  153. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/lambda-permission-eventbridge-multiple.json +0 -0
  154. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/lambda-permission-public-url.json +0 -0
  155. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/lambda-permission-s3-trigger.json +0 -0
  156. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/opensearch-domain-policy-ip-restricted.json +0 -0
  157. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-cloudfront.json +0 -0
  158. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-cross-account-org.json +0 -0
  159. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-insecure-transport.json +0 -0
  160. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-ip-restriction.json +0 -0
  161. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-public-with-conditions.json +0 -0
  162. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-public.json +0 -0
  163. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-specific-account.json +0 -0
  164. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-vpc-endpoint.json +0 -0
  165. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-wildcard-actions.json +0 -0
  166. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/secrets-manager-policy-cross-account.json +0 -0
  167. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sns-topic-policy-cross-account-mfa.json +0 -0
  168. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sns-topic-policy-cross-account.json +0 -0
  169. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sns-topic-policy-eventbridge.json +0 -0
  170. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sns-topic-policy-org-wide.json +0 -0
  171. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sns-topic-policy-public-no-conditions.json +0 -0
  172. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sqs-queue-policy-cross-account-role.json +0 -0
  173. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sqs-queue-policy-iam-users-mfa.json +0 -0
  174. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sqs-queue-policy-public.json +0 -0
  175. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sqs-queue-policy-sns-subscription.json +0 -0
  176. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/service-control-policies/deny-root-account-usage.json +0 -0
  177. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/service-control-policies/require-mfa.json +0 -0
  178. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/service-control-policies/restrict-regions.json +0 -0
  179. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/correct-condition-wrong-key.json +0 -0
  180. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/dynamodb-wrong-resources.json +0 -0
  181. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/ec2-wrong-resources.json +0 -0
  182. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/iam-wrong-resources.json +0 -0
  183. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/lambda-wrong-resources.json +0 -0
  184. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/s3-wrong-resources.json +0 -0
  185. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/sqs-sns-wrong-resources.json +0 -0
  186. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/typo-condition-field.json +0 -0
  187. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/mcp-llm-instructions/README.md +0 -0
  188. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/mcp-llm-instructions/SYSTEM_PROMPT.md +0 -0
  189. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/mcp-llm-instructions/example_conversation.md +0 -0
  190. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/mcp-llm-instructions/organization_config.yaml +0 -0
  191. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/quick-start/lambda-policy.json +0 -0
  192. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/quick-start/s3-policy.json +0 -0
  193. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/quick-start/user-policy.json +0 -0
  194. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/trust-policies/INVALID-wrong-principal-type.json +0 -0
  195. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/trust-policies/cross-account-trust-policy.json +0 -0
  196. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/trust-policies/github-actions-oidc-trust-policy.json +0 -0
  197. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/trust-policies/lambda-service-role-trust-policy.json +0 -0
  198. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/trust-policies/saml-federated-trust-policy.json +0 -0
  199. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/__init__.py +0 -0
  200. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/__main__.py +0 -0
  201. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/action_condition_enforcement.py +0 -0
  202. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/action_resource_matching.py +0 -0
  203. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/action_validation.py +0 -0
  204. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/full_wildcard.py +0 -0
  205. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/mfa_condition_check.py +0 -0
  206. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/not_action_not_resource.py +0 -0
  207. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/policy_size.py +0 -0
  208. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/policy_structure.py +0 -0
  209. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/policy_type_validation.py +0 -0
  210. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/principal_validation.py +0 -0
  211. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/resource_validation.py +0 -0
  212. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/sensitive_action.py +0 -0
  213. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/service_wildcard.py +0 -0
  214. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/sid_uniqueness.py +0 -0
  215. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/trust_policy_validation.py +0 -0
  216. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/utils/__init__.py +0 -0
  217. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/utils/action_parser.py +0 -0
  218. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/utils/policy_level_checks.py +0 -0
  219. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/utils/sensitive_action_matcher.py +0 -0
  220. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/utils/wildcard_expansion.py +0 -0
  221. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/wildcard_action.py +0 -0
  222. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/wildcard_resource.py +0 -0
  223. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/__init__.py +0 -0
  224. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/analyze.py +0 -0
  225. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/base.py +0 -0
  226. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/cache.py +0 -0
  227. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/completion.py +0 -0
  228. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/download_services.py +0 -0
  229. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/mcp.py +0 -0
  230. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/post_to_pr.py +0 -0
  231. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/query.py +0 -0
  232. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/validate.py +0 -0
  233. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/__init__.py +0 -0
  234. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/access_analyzer.py +0 -0
  235. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/access_analyzer_report.py +0 -0
  236. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_fetcher.py +0 -0
  237. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/__init__.py +0 -0
  238. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/cache.py +0 -0
  239. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/client.py +0 -0
  240. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/fetcher.py +0 -0
  241. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/parsers.py +0 -0
  242. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/patterns.py +0 -0
  243. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/storage.py +0 -0
  244. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/validators.py +0 -0
  245. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/cli.py +0 -0
  246. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/codeowners.py +0 -0
  247. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/__init__.py +0 -0
  248. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/aws_api.py +0 -0
  249. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/aws_global_conditions.py +0 -0
  250. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/category_suggestions.py +0 -0
  251. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/check_documentation.py +0 -0
  252. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/condition_requirements.py +0 -0
  253. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/config_loader.py +0 -0
  254. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/defaults.py +0 -0
  255. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/principal_requirements.py +0 -0
  256. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/sensitive_actions.py +0 -0
  257. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/service_principals.py +0 -0
  258. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/wildcards.py +0 -0
  259. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/constants.py +0 -0
  260. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/diff_parser.py +0 -0
  261. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/finding_fingerprint.py +0 -0
  262. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/__init__.py +0 -0
  263. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/base.py +0 -0
  264. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/console.py +0 -0
  265. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/csv.py +0 -0
  266. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/enhanced.py +0 -0
  267. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/html.py +0 -0
  268. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/json.py +0 -0
  269. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/markdown.py +0 -0
  270. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/sarif.py +0 -0
  271. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/ignore_patterns.py +0 -0
  272. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/ignore_processor.py +0 -0
  273. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/ignored_findings.py +0 -0
  274. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/label_manager.py +0 -0
  275. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/models.py +0 -0
  276. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/policy_checks.py +0 -0
  277. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/policy_loader.py +0 -0
  278. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/pr_commenter.py +0 -0
  279. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/report.py +0 -0
  280. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/integrations/__init__.py +0 -0
  281. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/integrations/github_integration.py +0 -0
  282. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/integrations/ms_teams.py +0 -0
  283. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/__init__.py +0 -0
  284. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/models.py +0 -0
  285. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/server.py +0 -0
  286. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/session_config.py +0 -0
  287. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/templates/__init__.py +0 -0
  288. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/templates/builtin.py +0 -0
  289. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/tools/__init__.py +0 -0
  290. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/tools/generation.py +0 -0
  291. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/tools/org_config_tools.py +0 -0
  292. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/tools/query.py +0 -0
  293. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/tools/validation.py +0 -0
  294. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/__init__.py +0 -0
  295. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/arn_matching.py +0 -0
  296. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/context.py +0 -0
  297. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/exceptions.py +0 -0
  298. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/helpers.py +0 -0
  299. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/policy_utils.py +0 -0
  300. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/query_utils.py +0 -0
  301. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/shortcuts.py +0 -0
  302. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/utils/__init__.py +0 -0
  303. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/utils/cache.py +0 -0
  304. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/utils/regex.py +0 -0
  305. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/utils/terminal.py +0 -0
  306. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/mkdocs.yml +0 -0
  307. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/pyproject.toml +0 -0
  308. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/README.md +0 -0
  309. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/__init__.py +0 -0
  310. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/__init__.py +0 -0
  311. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_action_validation_check.py +0 -0
  312. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_aws_global_conditions.py +0 -0
  313. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_custom_policy_checks.py +0 -0
  314. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_full_wildcard_check.py +0 -0
  315. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_mfa_condition_check.py +0 -0
  316. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_not_action_not_resource.py +0 -0
  317. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_policy_size_check.py +0 -0
  318. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_principal_validation_check.py +0 -0
  319. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_resource_validation_check.py +0 -0
  320. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_sensitive_action_filtering.py +0 -0
  321. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_sensitive_action_suggestions.py +0 -0
  322. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_sensitive_action_wildcard_expansion.py +0 -0
  323. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_service_principal_wildcard.py +0 -0
  324. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_service_wildcard_check.py +0 -0
  325. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_sid_uniqueness_check.py +0 -0
  326. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_wildcard_action_check.py +0 -0
  327. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_wildcard_resource_check.py +0 -0
  328. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/commands/__init__.py +0 -0
  329. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/commands/test_completion_command.py +0 -0
  330. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/commands/test_query_command.py +0 -0
  331. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/config/__init__.py +0 -0
  332. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/config/test_config_loader.py +0 -0
  333. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/__init__.py +0 -0
  334. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_action_condition_enforcement.py +0 -0
  335. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_action_condition_enforcement_policy_level.py +0 -0
  336. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_action_resource_matching.py +0 -0
  337. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_aws_api_config.py +0 -0
  338. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_aws_fetcher_wildcards.py +0 -0
  339. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_check_id_in_comments.py +0 -0
  340. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_check_id_injection.py +0 -0
  341. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_check_registry.py +0 -0
  342. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_codeowners.py +0 -0
  343. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_comment_truncation.py +0 -0
  344. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_diff_parser.py +0 -0
  345. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_finding_fingerprint.py +0 -0
  346. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_ignore_patterns.py +0 -0
  347. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_ignored_findings.py +0 -0
  348. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_models.py +0 -0
  349. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_multipart_comments.py +0 -0
  350. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_policy_loader.py +0 -0
  351. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_policy_type_validation.py +0 -0
  352. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_pr_commenter_diff_filtering.py +0 -0
  353. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_regex_utils.py +0 -0
  354. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_trust_policy_detection.py +0 -0
  355. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_trust_policy_multiple_statements.py +0 -0
  356. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_trust_policy_oidc_aud_required.py +0 -0
  357. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_trust_policy_validation.py +0 -0
  358. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/integrations/__init__.py +0 -0
  359. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/integrations/test_comment_deduplication.py +0 -0
  360. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/integrations/test_github_pagination.py +0 -0
  361. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/integrations/test_label_manager.py +0 -0
  362. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/__init__.py +0 -0
  363. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/conftest.py +0 -0
  364. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_custom_instructions.py +0 -0
  365. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_generation_tools.py +0 -0
  366. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_org_config.py +0 -0
  367. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_query_tools.py +0 -0
  368. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_server_integration.py +0 -0
  369. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_templates.py +0 -0
  370. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_validation_tools.py +0 -0
  371. {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/uv.lock +0 -0
@@ -26,7 +26,7 @@ jobs:
26
26
  python-version: "${{ env.DEFAULT_PYTHON_VERSION }}"
27
27
 
28
28
  - name: Install uv
29
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
29
+ uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
30
30
  with:
31
31
  enable-cache: true
32
32
 
@@ -56,7 +56,7 @@ jobs:
56
56
  python-version: ${{ matrix.python-version }}
57
57
 
58
58
  - name: Install uv
59
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
59
+ uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
60
60
  with:
61
61
  enable-cache: true
62
62
 
@@ -80,7 +80,7 @@ jobs:
80
80
  python-version: "${{ env.DEFAULT_PYTHON_VERSION }}"
81
81
 
82
82
  - name: Install uv
83
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
83
+ uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
84
84
  with:
85
85
  enable-cache: true
86
86
 
@@ -104,7 +104,7 @@ jobs:
104
104
  python-version: "${{ env.DEFAULT_PYTHON_VERSION }}"
105
105
 
106
106
  - name: Install uv
107
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
107
+ uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
108
108
  with:
109
109
  enable-cache: true
110
110
 
@@ -80,7 +80,7 @@ jobs:
80
80
  python-version: ${{ inputs.python_version }}
81
81
 
82
82
  - name: Install uv
83
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
83
+ uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
84
84
  with:
85
85
  enable-cache: true
86
86
 
@@ -31,7 +31,7 @@ jobs:
31
31
  python-version: ${{ env.PYTHON_VERSION }}
32
32
 
33
33
  - name: Install uv
34
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
34
+ uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
35
35
  with:
36
36
  enable-cache: true
37
37
 
@@ -13,6 +13,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13
13
 
14
14
  ---
15
15
 
16
+ ## [1.16.0] - 2026-02-05
17
+
18
+ ### Added
19
+
20
+ - New `ifexists_condition_usage` check validating proper usage of the `IfExists` suffix on condition operators:
21
+ - Detects `IfExists` on security-sensitive keys in Allow statements (may bypass controls)
22
+ - Warns about non-negated `IfExists` weakening Deny statements
23
+ - Flags redundant `IfExists` on always-present keys (e.g., `aws:SecureTransport`)
24
+ - Optionally suggests `IfExists` for negated operators in Deny statements
25
+ - Security-sensitive and always-present condition key constants in `condition_validators` module
26
+
27
+ ### Improved
28
+
29
+ - `condition_key_validation`: Suppress false positive errors when `IfExists` is used with keys valid for some but not all actions in the statement
30
+ - `condition_type_mismatch`: Detect `NullIfExists` as invalid syntax (the `Null` operator already checks for key existence)
31
+ - `set_operator_validation`: Compound warning when `ForAllValues` is combined with `IfExists` (doubly permissive pattern)
32
+
33
+ ---
34
+
16
35
  ## [1.15.5] - 2025-01-28
17
36
 
18
37
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iam-policy-validator
3
- Version: 1.15.6
3
+ Version: 1.16.0
4
4
  Summary: Validate AWS IAM policies for correctness and security using AWS Service Reference API
5
5
  Project-URL: Homepage, https://github.com/boogy/iam-policy-validator
6
6
  Project-URL: Documentation, https://boogy.github.io/iam-policy-validator
@@ -183,7 +183,7 @@ runs:
183
183
  python-version-file: "${{ github.action_path }}/.python-version"
184
184
 
185
185
  - name: Install uv
186
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
186
+ uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
187
187
  with:
188
188
  enable-cache: true
189
189
  cache-suffix: ci # Prune cache in CI to reduce bloat
@@ -211,7 +211,7 @@ runs:
211
211
 
212
212
  - name: Restore AWS service definitions cache
213
213
  id: cache-aws-services
214
- uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
214
+ uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
215
215
  with:
216
216
  path: ~/.cache/iam-validator/aws_services
217
217
  # Cache key refreshes weekly to get latest AWS service updates
@@ -553,7 +553,7 @@ runs:
553
553
  # Attempting to save with an existing key will silently do nothing
554
554
  # Use always() to ensure cache is saved even if validation fails
555
555
  if: always() && steps.cache-aws-services.outputs.cache-hit != 'true'
556
- uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
556
+ uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
557
557
  with:
558
558
  path: ~/.cache/iam-validator/aws_services
559
559
  key: aws-services-${{ runner.os }}-${{ steps.week.outputs.week }}
@@ -3,7 +3,7 @@
3
3
  This file is the single source of truth for the package version.
4
4
  """
5
5
 
6
- __version__ = "1.15.6"
6
+ __version__ = "1.16.0"
7
7
  # Parse version, handling pre-release suffixes like -rc, -alpha, -beta
8
8
  _version_base = __version__.split("-", maxsplit=1)[0] # Remove pre-release suffix if present
9
9
  __version_info__ = tuple(int(part) for part in _version_base.split("."))
@@ -10,6 +10,7 @@ from iam_validator.checks.action_validation import ActionValidationCheck
10
10
  from iam_validator.checks.condition_key_validation import ConditionKeyValidationCheck
11
11
  from iam_validator.checks.condition_type_mismatch import ConditionTypeMismatchCheck
12
12
  from iam_validator.checks.full_wildcard import FullWildcardCheck
13
+ from iam_validator.checks.ifexists_condition_check import IfExistsConditionCheck
13
14
  from iam_validator.checks.mfa_condition_check import MFAConditionCheck
14
15
  from iam_validator.checks.not_action_not_resource import NotActionNotResourceCheck
15
16
  from iam_validator.checks.policy_size import PolicySizeCheck
@@ -31,6 +32,7 @@ __all__ = [
31
32
  "ConditionKeyValidationCheck",
32
33
  "ConditionTypeMismatchCheck",
33
34
  "FullWildcardCheck",
35
+ "IfExistsConditionCheck",
34
36
  "MFAConditionCheck",
35
37
  "NotActionNotResourceCheck",
36
38
  "PolicySizeCheck",
@@ -0,0 +1,125 @@
1
+ """Condition key validation check - validates condition keys against AWS definitions."""
2
+
3
+ from typing import ClassVar
4
+
5
+ from iam_validator.core.aws_service import AWSServiceFetcher
6
+ from iam_validator.core.check_registry import CheckConfig, PolicyCheck
7
+ from iam_validator.core.condition_validators import has_if_exists_suffix
8
+ from iam_validator.core.models import Statement, ValidationIssue
9
+
10
+
11
+ class ConditionKeyValidationCheck(PolicyCheck):
12
+ """Validates condition keys against AWS service definitions and global keys."""
13
+
14
+ check_id: ClassVar[str] = "condition_key_validation"
15
+ description: ClassVar[str] = "Validates condition keys against AWS service definitions"
16
+ default_severity: ClassVar[str] = "error" # Invalid condition keys are IAM policy errors
17
+
18
+ async def execute(
19
+ self,
20
+ statement: Statement,
21
+ statement_idx: int,
22
+ fetcher: AWSServiceFetcher,
23
+ config: CheckConfig,
24
+ ) -> list[ValidationIssue]:
25
+ """Execute condition key validation on a statement."""
26
+ issues = []
27
+
28
+ # Get conditions from statement
29
+ if not statement.condition:
30
+ return issues
31
+
32
+ # Check if global condition key warnings are enabled (default: True)
33
+ warn_on_global_keys = config.config.get("warn_on_global_condition_keys", True)
34
+
35
+ statement_sid = statement.sid
36
+ line_number = statement.line_number
37
+ actions = statement.get_actions()
38
+ resources = statement.get_resources()
39
+
40
+ # Extract all condition keys from all condition operators
41
+ for operator, conditions in statement.condition.items():
42
+ operator_has_ifexists = has_if_exists_suffix(operator)
43
+
44
+ for condition_key in conditions.keys():
45
+ key_valid_for_any_action = False
46
+ key_invalid_actions: list[tuple] = []
47
+ first_warning_result = None
48
+
49
+ # Validate this condition key against each action in the statement
50
+ for action in actions:
51
+ # Skip wildcard actions
52
+ if action == "*":
53
+ continue
54
+
55
+ # Validate against action and resource types
56
+ result = await fetcher.validate_condition_key(action, condition_key, resources)
57
+
58
+ if result.is_valid:
59
+ key_valid_for_any_action = True
60
+ if result.warning_message and first_warning_result is None:
61
+ first_warning_result = (action, result)
62
+ else:
63
+ key_invalid_actions.append((action, result))
64
+
65
+ # If IfExists is used and the key is valid for at least one action,
66
+ # suppress errors for actions that don't support it.
67
+ # Warnings (global key usage) are still reported.
68
+ if operator_has_ifexists and key_valid_for_any_action:
69
+ if first_warning_result and warn_on_global_keys:
70
+ action, result = first_warning_result
71
+ warning_msg = result.warning_message or ""
72
+ issues.append(
73
+ ValidationIssue(
74
+ severity="warning",
75
+ statement_sid=statement_sid,
76
+ statement_index=statement_idx,
77
+ issue_type="global_condition_key_with_action_specific",
78
+ message=warning_msg,
79
+ action=action,
80
+ condition_key=condition_key,
81
+ line_number=line_number,
82
+ field_name="condition",
83
+ )
84
+ )
85
+ continue # Skip error reporting
86
+
87
+ # Report errors (first invalid action)
88
+ if key_invalid_actions:
89
+ action, result = key_invalid_actions[0]
90
+ issues.append(
91
+ ValidationIssue(
92
+ severity=self.get_severity(config),
93
+ statement_sid=statement_sid,
94
+ statement_index=statement_idx,
95
+ issue_type="invalid_condition_key",
96
+ message=result.error_message
97
+ or f"Invalid condition key: `{condition_key}`",
98
+ action=action,
99
+ condition_key=condition_key,
100
+ line_number=line_number,
101
+ suggestion=result.suggestion,
102
+ field_name="condition",
103
+ )
104
+ )
105
+ continue
106
+
107
+ # Report warnings for valid keys (no IfExists suppression path)
108
+ if first_warning_result and warn_on_global_keys:
109
+ action, result = first_warning_result
110
+ warning_msg = result.warning_message or ""
111
+ issues.append(
112
+ ValidationIssue(
113
+ severity="warning",
114
+ statement_sid=statement_sid,
115
+ statement_index=statement_idx,
116
+ issue_type="global_condition_key_with_action_specific",
117
+ message=warning_msg,
118
+ action=action,
119
+ condition_key=condition_key,
120
+ line_number=line_number,
121
+ field_name="condition",
122
+ )
123
+ )
124
+
125
+ return issues
@@ -8,6 +8,7 @@ from typing import ClassVar
8
8
  from iam_validator.core.aws_service import AWSServiceFetcher
9
9
  from iam_validator.core.check_registry import CheckConfig, PolicyCheck
10
10
  from iam_validator.core.condition_validators import (
11
+ has_if_exists_suffix,
11
12
  normalize_operator,
12
13
  translate_type,
13
14
  validate_value_for_type,
@@ -71,6 +72,25 @@ class ConditionTypeMismatchCheck(PolicyCheck):
71
72
  # Unknown operator - this will be caught by another check
72
73
  continue
73
74
 
75
+ # Detect NullIfExists as invalid syntax (must be BEFORE skip_operators guard)
76
+ if base_operator == "Null" and has_if_exists_suffix(operator):
77
+ issues.append(
78
+ ValidationIssue(
79
+ severity=self.get_severity(config),
80
+ message=(
81
+ f"Invalid operator `{operator}`. The `Null` condition operator "
82
+ f"does not support the `IfExists` suffix. The `Null` operator "
83
+ f"already checks for key existence \u2014 use `Null` directly."
84
+ ),
85
+ statement_sid=statement_sid,
86
+ statement_index=statement_idx,
87
+ issue_type="invalid_operator",
88
+ line_number=line_number,
89
+ field_name="condition",
90
+ )
91
+ )
92
+ continue
93
+
74
94
  if base_operator in skip_operators:
75
95
  continue
76
96
 
@@ -0,0 +1,210 @@
1
+ """IfExists Condition Usage Check.
2
+
3
+ Validates proper usage of the IfExists suffix on IAM condition operators.
4
+
5
+ Detects:
6
+ - IfExists on security-sensitive keys in Allow statements (may bypass controls)
7
+ - Non-negated IfExists in Deny statements (weakens the Deny)
8
+ - IfExists on always-present keys (redundant)
9
+ - Suggests IfExists for negated operators in Deny without it
10
+ """
11
+
12
+ from typing import ClassVar
13
+
14
+ from iam_validator.core.aws_service import AWSServiceFetcher
15
+ from iam_validator.core.check_registry import CheckConfig, PolicyCheck
16
+ from iam_validator.core.condition_validators import (
17
+ ALWAYS_PRESENT_CONDITION_KEYS,
18
+ SECURITY_SENSITIVE_CONDITION_KEYS,
19
+ has_if_exists_suffix,
20
+ is_negated_operator,
21
+ normalize_operator,
22
+ )
23
+ from iam_validator.core.models import Statement, ValidationIssue
24
+
25
+
26
+ class IfExistsConditionCheck(PolicyCheck):
27
+ """Check for improper or risky usage of IfExists condition operators."""
28
+
29
+ check_id: ClassVar[str] = "ifexists_condition_usage"
30
+ description: ClassVar[str] = "Validates proper usage of IfExists suffix on condition operators"
31
+ default_severity: ClassVar[str] = "warning"
32
+
33
+ async def execute(
34
+ self,
35
+ statement: Statement,
36
+ statement_idx: int,
37
+ fetcher: AWSServiceFetcher,
38
+ config: CheckConfig,
39
+ ) -> list[ValidationIssue]:
40
+ """Execute IfExists condition usage checks."""
41
+ issues: list[ValidationIssue] = []
42
+
43
+ if not statement.condition:
44
+ return issues
45
+
46
+ statement_sid = statement.sid
47
+ line_number = statement.line_number
48
+ effect = statement.effect
49
+
50
+ # Config options
51
+ warn_security_sensitive_allow = config.config.get("warn_security_sensitive_allow", True)
52
+ suggest_deny_ifexists = config.config.get("suggest_deny_ifexists", False)
53
+ warn_always_present_keys = config.config.get("warn_always_present_keys", True)
54
+ additional_security_keys = config.config.get("additional_security_sensitive_keys", [])
55
+
56
+ # Build the full set of security-sensitive keys
57
+ security_keys = SECURITY_SENSITIVE_CONDITION_KEYS | frozenset(additional_security_keys)
58
+
59
+ # Collect Null-checked keys for suppression
60
+ null_checked_keys: set[str] = set()
61
+ for op, conds in statement.condition.items():
62
+ base_op, _, _ = normalize_operator(op)
63
+ if base_op == "Null":
64
+ for key, value in conds.items():
65
+ # Only suppress if Null checks for key presence (value = "false")
66
+ values = value if isinstance(value, list) else [value]
67
+ if any(str(v).lower() == "false" for v in values):
68
+ null_checked_keys.add(key)
69
+
70
+ for operator, conditions in statement.condition.items():
71
+ has_ifexists = has_if_exists_suffix(operator)
72
+ is_negated = is_negated_operator(operator)
73
+ base_op, _, _ = normalize_operator(operator)
74
+
75
+ for condition_key in conditions:
76
+ # Normalize condition key for case-insensitive comparison
77
+ key_lower = condition_key.lower()
78
+
79
+ # Skip MFA key - handled by mfa_condition_antipattern check
80
+ if key_lower == "aws:multifactorauthpresent":
81
+ continue
82
+
83
+ if has_ifexists:
84
+ # IfExists on always-present keys is redundant
85
+ if warn_always_present_keys:
86
+ always_present_match = any(
87
+ k.lower() == key_lower for k in ALWAYS_PRESENT_CONDITION_KEYS
88
+ )
89
+ if always_present_match:
90
+ # Reconstruct the operator without IfExists for the message
91
+ raw_base = operator
92
+ if ":" in operator:
93
+ parts = operator.split(":", 1)
94
+ if parts[0] in ("ForAllValues", "ForAnyValue"):
95
+ raw_base = parts[1]
96
+ base_without_ifexists = (
97
+ raw_base[:-8] if raw_base.endswith("IfExists") else raw_base
98
+ )
99
+ if ":" in operator:
100
+ parts = operator.split(":", 1)
101
+ if parts[0] in ("ForAllValues", "ForAnyValue"):
102
+ base_without_ifexists = f"{parts[0]}:{base_without_ifexists}"
103
+
104
+ issues.append(
105
+ ValidationIssue(
106
+ severity="info",
107
+ message=(
108
+ f"Redundant `IfExists`: The condition key "
109
+ f"`{condition_key}` is always present in the "
110
+ f"request context. Using `{operator}` has the "
111
+ f"same effect as `{base_without_ifexists}` for "
112
+ f"this key."
113
+ ),
114
+ statement_sid=statement_sid,
115
+ statement_index=statement_idx,
116
+ issue_type="ifexists_on_always_present_key",
117
+ condition_key=condition_key,
118
+ line_number=line_number,
119
+ field_name="condition",
120
+ )
121
+ )
122
+
123
+ # Check if key is security-sensitive (case-insensitive)
124
+ is_security_key = any(k.lower() == key_lower for k in security_keys)
125
+
126
+ if effect == "Allow" and warn_security_sensitive_allow:
127
+ # IfExists on security-sensitive keys in Allow may bypass controls
128
+ if is_security_key:
129
+ # Check for complementary Null check
130
+ if condition_key not in null_checked_keys:
131
+ issues.append(
132
+ ValidationIssue(
133
+ severity=self.get_severity(config),
134
+ message=(
135
+ f"Security control may be bypassed: "
136
+ f"`{operator}` with `{condition_key}` in "
137
+ f"an Allow statement means the restriction "
138
+ f"is not enforced when the key is missing "
139
+ f"from the request context. Not all API "
140
+ f"calls include `{condition_key}` (e.g., "
141
+ f"calls made by AWS services on your "
142
+ f"behalf). Consider using the operator "
143
+ f"without `IfExists` or adding a `Null` "
144
+ f"condition check."
145
+ ),
146
+ statement_sid=statement_sid,
147
+ statement_index=statement_idx,
148
+ issue_type="ifexists_weakens_security_condition",
149
+ condition_key=condition_key,
150
+ line_number=line_number,
151
+ field_name="condition",
152
+ )
153
+ )
154
+
155
+ elif effect == "Deny":
156
+ # Non-negated IfExists in Deny weakens the restriction
157
+ if not is_negated and is_security_key:
158
+ if condition_key not in null_checked_keys:
159
+ issues.append(
160
+ ValidationIssue(
161
+ severity=self.get_severity(config),
162
+ message=(
163
+ f"Weakened Deny: `{operator}` with "
164
+ f"`{condition_key}` in a Deny statement "
165
+ f"means the Deny does not apply when "
166
+ f"`{condition_key}` is missing from the "
167
+ f"request context. Consider removing "
168
+ f"`IfExists` or adding a `Null` condition "
169
+ f"check."
170
+ ),
171
+ statement_sid=statement_sid,
172
+ statement_index=statement_idx,
173
+ issue_type="ifexists_weakens_deny",
174
+ condition_key=condition_key,
175
+ line_number=line_number,
176
+ field_name="condition",
177
+ )
178
+ )
179
+
180
+ elif not has_ifexists and effect == "Deny" and suggest_deny_ifexists:
181
+ # Suggest IfExists for negated operator in Deny without it
182
+ if is_negated:
183
+ # Only suggest for keys that may be absent
184
+ is_always_present = any(
185
+ k.lower() == key_lower for k in ALWAYS_PRESENT_CONDITION_KEYS
186
+ )
187
+ is_security_key = any(k.lower() == key_lower for k in security_keys)
188
+ if not is_always_present and is_security_key:
189
+ issues.append(
190
+ ValidationIssue(
191
+ severity="info",
192
+ message=(
193
+ f"Consider using `{base_op}IfExists` instead "
194
+ f"of `{base_op}` in this Deny statement. "
195
+ f"Without `IfExists`, the Deny does not apply "
196
+ f"when `{condition_key}` is missing from the "
197
+ f"request context. With `{base_op}IfExists`, "
198
+ f"the Deny still applies even when the key is "
199
+ f"absent."
200
+ ),
201
+ statement_sid=statement_sid,
202
+ statement_index=statement_idx,
203
+ issue_type="ifexists_deny_suggestion",
204
+ condition_key=condition_key,
205
+ line_number=line_number,
206
+ field_name="condition",
207
+ )
208
+ )
209
+
210
+ return issues
@@ -11,6 +11,7 @@ from typing import ClassVar
11
11
  from iam_validator.core.aws_service import AWSServiceFetcher
12
12
  from iam_validator.core.check_registry import CheckConfig, PolicyCheck
13
13
  from iam_validator.core.condition_validators import (
14
+ has_if_exists_suffix,
14
15
  is_multivalued_context_key,
15
16
  normalize_operator,
16
17
  )
@@ -81,6 +82,7 @@ class SetOperatorValidationCheck(PolicyCheck):
81
82
  # Second pass: Validate set operator usage
82
83
  for operator, conditions in statement.condition.items():
83
84
  base_operator, _operator_type, set_prefix = normalize_operator(operator)
85
+ has_ifexists = has_if_exists_suffix(operator)
84
86
 
85
87
  if not set_prefix:
86
88
  continue
@@ -110,15 +112,27 @@ class SetOperatorValidationCheck(PolicyCheck):
110
112
  # Issue 2: ForAllValues with Allow effect without Null check (security risk)
111
113
  if set_prefix == "ForAllValues" and effect == "Allow":
112
114
  if condition_key not in null_checked_keys:
115
+ if has_ifexists:
116
+ message = (
117
+ f"Compounded security risk: `{operator}` with `Allow` effect "
118
+ f"on `{condition_key}` is doubly permissive. `ForAllValues` "
119
+ f"passes when the value set is empty, and `IfExists` passes "
120
+ f"when the key is missing entirely. Both mechanisms "
121
+ f"independently allow access without matching any values. "
122
+ f'Add: `"Null": {{"{condition_key}": "false"}}` and consider '
123
+ f"removing `IfExists`."
124
+ )
125
+ else:
126
+ message = (
127
+ f"Security risk: `ForAllValues` with `Allow` effect on `{condition_key}` "
128
+ f"should include a `Null` condition check. Without it, requests with missing "
129
+ f'`{condition_key}` will be granted access. Add: `"Null": {{"{condition_key}": "false"}}`. '
130
+ f"See: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html"
131
+ )
113
132
  issues.append(
114
133
  ValidationIssue(
115
134
  severity="warning",
116
- message=(
117
- f"Security risk: `ForAllValues` with `Allow` effect on `{condition_key}` "
118
- f"should include a `Null` condition check. Without it, requests with missing "
119
- f'`{condition_key}` will be granted access. Add: `"Null": {{"{condition_key}": "false"}}`. '
120
- f"See: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html"
121
- ),
135
+ message=message,
122
136
  statement_sid=statement_sid,
123
137
  statement_index=statement_idx,
124
138
  issue_type="forallvalues_allow_without_null_check",
@@ -706,6 +706,7 @@ def create_default_registry(
706
706
  # 3. TYPE VALIDATION (Condition operator type checking)
707
707
  registry.register(checks.ConditionTypeMismatchCheck()) # Operator-value type compatibility
708
708
  registry.register(checks.SetOperatorValidationCheck()) # ForAllValues/ForAnyValue usage
709
+ registry.register(checks.IfExistsConditionCheck()) # IfExists usage validation
709
710
 
710
711
  # 4. RESOURCE MATCHING (Action-resource relationship validation)
711
712
  registry.register(