Common Gotchas with ForAllValues and ForAnyValue IAM Condition Operators

When using ForAllValues and ForAnyValue IAM condition operators, always verify the condition key is array-typed, pair ForAllValues with a Null:false check to prevent vacuous truth, and add explicit Null denies for ForAnyValue to ensure missing keys trigger denials.

The ForAllValues and ForAnyValue IAM condition operators enable powerful multi-value matching for array-typed context keys like aws:TagKeys or aws:VpceOrgPaths. However, these operators contain strict logical semantics that can unintentionally grant broad access or fail to trigger denials when keys are missing. The Agent Toolkit for AWS (aws/agent-toolkit-for-aws) documents these critical edge cases in skills/core-skills/aws-iam/references/common-pitfalls.md to help you avoid security holes in your IAM policies.

Applying Set Operators to Scalar Keys

The ForAllValues and ForAnyValue prefixes are designed exclusively for array-typed condition keys (ArrayOfString, ArrayOfARN, ArrayOfNumeric). Applying these operators to scalar keys (e.g., String, Bool) results in undefined behavior that may cause the policy engine to misinterpret your intent.

Before using set operators, verify the key type in the service reference's ConditionKeys list. For scalar keys, use standard operators like StringEquals or StringNotLike instead.

Incorrect: Using ForAnyValue on the scalar key dynamodb:EnclosingOperation.

{
  "Effect": "Allow",
  "Action": "dynamodb:Query",
  "Resource": "*",
  "Condition": {
    "ForAnyValue:StringEquals": { "dynamodb:EnclosingOperation": "Scan" }
  }
}

Correct: Use scalar operators for scalar keys.

{
  "Effect": "Allow",
  "Action": "dynamodb:Query",
  "Resource": "*",
  "Condition": {
    "StringEquals": { "dynamodb:EnclosingOperation": "Scan" }
  }
}

ForAnyValue in Deny Statements Without Null Checks

When a context key is missing, ForAnyValue evaluates to FALSE due to the logical definition of "any value satisfies X" being false for empty sets. In a Deny statement, this means the denial never triggers, potentially allowing requests to bypass your intended restrictions.

To prevent this, add a separate Null check to explicitly deny requests that lack the required key.

Incorrect: A deny that fails to block requests when aws:VpceOrgPaths is absent.

{
  "Effect": "Deny",
  "Principal": "*",
  "Action": ["s3:GetObject", "s3:PutObject"],
  "Resource": "arn:aws:s3:::my-bucket/*",
  "Condition": {
    "ForAnyValue:StringNotLike": {
      "aws:VpceOrgPaths": "o-abcdefg/r-12345/ou-123456/*"
    }
  }
}

Correct: Add a separate statement to deny missing keys.

{
  "Effect": "Deny",
  "Principal": "*",
  "Action": ["s3:GetObject", "s3:PutObject"],
  "Resource": "arn:aws:s3:::my-bucket/*",
  "Condition": {
    "ForAnyValue:StringNotLike": {
      "aws:VpceOrgPaths": "o-abcdefg/r-12345/ou-123456/*"
    }
  }
},
{
  "Effect": "Deny",
  "Principal": "*",
  "Action": ["s3:GetObject", "s3:PutObject"],
  "Resource": "arn:aws:s3:::my-bucket/*",
  "Condition": {
    "Null": { "aws:VpceOrgPaths": "true" }
  }
}

ForAllValues in Allow Statements and Vacuous Truth

ForAllValues exhibits vacuous truth: when the context key is missing, the condition evaluates to TRUE because "all values satisfy X" is logically true for empty sets. An Allow statement containing only ForAllValues will therefore grant access even when the key is absent, creating a security hole.

According to the aws/agent-toolkit-for-aws source code in skills/core-skills/aws-iam/references/common-pitfalls.md, you must include a Null condition requiring the key's presence before evaluating the ForAllValues check.

Incorrect: Grants permission when aws:TagKeys is not supplied.

{
  "Effect": "Allow",
  "Action": "s3:PutObject",
  "Resource": "*",
  "Condition": {
    "ForAllValues:StringEquals": { "aws:TagKeys": "a" }
  }
}

Correct: Require the key to exist using Null:false.

{
  "Effect": "Allow",
  "Action": "s3:PutObject",
  "Resource": "*",
  "Condition": {
    "Null": { "aws:TagKeys": "false" },
    "ForAllValues:StringEquals": { "aws:TagKeys": "a" }
  }
}

Missing Required Actions for Multi-Operation APIs

Some AWS operations require multiple IAM actions to function correctly. For example, dynamodb:BatchExecuteStatement requires four PartiQL actions (dynamodb:PartiQLDelete, dynamodb:PartiQLInsert, dynamodb:PartiQLSelect, dynamodb:PartiQLUpdate). Omitting any required action leads to runtime failures even if your conditions are correct.

Consult the service authorization reference and add all needed actions to your policy.

{
  "Effect": "Allow",
  "Action": [
    "dynamodb:BatchExecuteStatement",
    "dynamodb:PartiQLDelete",
    "dynamodb:PartiQLInsert",
    "dynamodb:PartiQLSelect",
    "dynamodb:PartiQLUpdate"
  ],
  "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable"
}

Summary

  • Verify key types before using ForAllValues or ForAnyValue; these operators only work with array-typed keys (ArrayOfString, ArrayOfARN, etc.) and produce undefined behavior on scalars.
  • Guard ForAllValues with Null:false to prevent vacuous truth from allowing requests when keys are missing.
  • Add explicit Null denies when using ForAnyValue in deny statements to ensure missing keys trigger denials rather than evaluating to false.
  • Include all required actions for multi-operation APIs like DynamoDB's BatchExecuteStatement to avoid runtime authorization failures.
  • Reference skills/core-skills/aws-iam/references/common-pitfalls.md and skills/core-skills/aws-iam/references/aws-iam-policy-generation.md in the Agent Toolkit for AWS repository for the complete policy generation checklist.

Frequently Asked Questions

What happens if I use ForAllValues in an Allow statement without a Null check?

The condition evaluates to TRUE when the context key is missing due to vacuous truth. This means your policy will grant access to requests that do not contain the expected key, creating a potential security vulnerability. Always add "Null": {"<key>": "false"} to require the key's presence.

Why does my ForAnyValue deny statement fail to block requests?

When the context key is absent, ForAnyValue evaluates to FALSE, causing the deny condition to never trigger. To block requests that lack the key, you must add a separate deny statement with a Null check (e.g., "Null": {"aws:VpceOrgPaths": "true"}) or combine it with the ForAnyValue condition.

Can I use ForAllValues or ForAnyValue with scalar condition keys like String or Bool?

No. These operators are designed exclusively for array-typed condition keys. Using them on scalar keys (String, Bool, Numeric) results in undefined behavior. Use standard scalar operators like StringEquals or Bool instead, as documented in skills/core-skills/aws-iam/references/common-pitfalls.md.

Where can I find the official documentation for these IAM condition operators?

The Agent Toolkit for AWS repository (aws/agent-toolkit-for-aws) maintains detailed references in skills/core-skills/aws-iam/references/common-pitfalls.md and skills/core-skills/aws-iam/references/aws-iam-policy-generation.md. These files provide the definitive checklist for safe policy creation with ForAllValues and ForAnyValue operators.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →