Fixing AWS IAM Role 'DurationSeconds Exceeds MaxSessionDuration' Error: Root Cause and Step-by-Step Resolution
Threat/Impact Level: HIGH | Exploitability/Downtime Risk: HIGH | Time to Fix: 5–15 mins
TL;DR
- What broke: Your
sts:AssumeRolecall requestedDurationSeconds=43200(12 hours), but the target IAM role'sMaxSessionDurationis set lower (default is 3600 seconds / 1 hour). - How to fix it: Either reduce
DurationSecondsin theAssumeRolecall to match or fall below the role'sMaxSessionDuration, or increaseMaxSessionDurationon the role itself (max ceiling: 43200). - Fast path: Use our Client-Side Sandbox below to auto-refactor this — paste your Terraform role resource or AWS CLI AssumeRole command and get corrected code instantly.
The Incident (What Does the Error Mean?)
Raw error output:
An error occurred (ValidationError) when calling the AssumeRole operation:
The requested DurationSeconds exceeds the 1 hour maximum session duration
established for this role. role maximum session duration exceeded 'DurationSeconds' 43200
Immediate consequence: The sts:AssumeRole call fails hard. No credentials are returned. Any process depending on those credentials — a CI/CD pipeline, a Lambda bootstrapper, a federated console login, a long-running ECS task — dies at the authentication boundary. There is no partial credential issuance; it's a binary failure.
The default MaxSessionDuration for every new IAM role is 3600 seconds (1 hour). If you or your tooling requests anything above that without explicitly raising the cap on the role, AWS rejects the call.
The Attack Vector / Blast Radius
This is a misconfiguration-driven availability failure with a secondary security dimension.
Availability blast radius:
- CI/CD pipelines using long-running assume-role chains (CodeBuild, GitHub Actions OIDC, Jenkins) fail at job start.
- Federated SSO sessions (AWS SSO, Okta SAML) that request extended console sessions are blocked.
- ECS/EKS workloads using task roles with extended credential refresh windows break silently mid-execution when the refresh call fails.
- Cross-account automation that chains multiple AssumeRole hops fails at the first hop exceeding the cap.
Security dimension — why the cap exists and why you must not blindly maximize it:
A session credential issued for 12 hours is a 12-hour exploitation window if that credential is exfiltrated. If an attacker compromises a long-lived session token (via SSRF on EC2 metadata, a leaked environment variable in a container log, or a misconfigured S3 bucket containing CI artifacts), they hold valid AWS credentials for the full session duration. STS cannot revoke individual session tokens without revoking the entire role's active sessions via sts:RevokeSession — a blunt instrument that breaks all current holders.
The correct posture is the minimum DurationSeconds your workload actually needs, not the maximum allowed.
How to Fix It (The Solution)
Basic Fix — Align DurationSeconds to the Existing Role Cap
If you don't control the role (cross-account, shared service role), reduce your AssumeRole call:
# AWS CLI
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/MyRole \
- --duration-seconds 43200 \
+ --duration-seconds 3600 \
--role-session-name my-session
Enterprise Best Practice — Raise MaxSessionDuration on the Role with Least-Privilege Guardrails
If your workload legitimately requires extended sessions (e.g., a 6-hour batch job, an 8-hour developer federation window), raise the cap on the role to exactly what is needed — not blindly to 43200.
Terraform (aws_iam_role resource):
resource "aws_iam_role" "batch_processor" {
name = "batch-processor-role"
assume_role_policy = data.aws_iam_policy_document.assume.json
- # max_session_duration not set — defaults to 3600
+ max_session_duration = 14400 # 4 hours — match your actual job SLA, not the ceiling
}
CloudFormation:
BatchProcessorRole:
Type: AWS::IAM::Role
Properties:
RoleName: batch-processor-role
AssumeRolePolicyDocument: !Ref AssumeRolePolicy
- # MaxSessionDuration: omitted (defaults to 3600)
+ MaxSessionDuration: 14400
Pair the extended duration with a condition key to restrict which principals can request long sessions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/GitHubActionsOIDC"
},
"Action": "sts:AssumeRole",
"Condition": {
"NumericLessThanEquals": {
"sts:DurationSeconds": "14400"
}
}
}
]
}
This trust policy condition hard-caps what any caller can request, even if MaxSessionDuration is set higher. Defense in depth.
💡 Tired of pasting proprietary configs into ChatGPT? Generic AI tools log your company's ARNs, DB strings, and private keys. StackEngine is a zero-backend, pure Client-Side WASM utility. Drop your failing config into the sandbox above. We redact your secrets locally in the browser and auto-generate the refactored code using your own API key.
Prevention in CI/CD
1. Checkov — Catch Uncapped MaxSessionDuration at PR Time
Checkov rule CKV_AWS_9 flags IAM roles without an explicit MaxSessionDuration. Add to your pipeline:
# .github/workflows/security-scan.yml
- name: Checkov IAM Scan
uses: bridgecrewio/checkov-action@master
with:
directory: ./terraform
check: CKV_AWS_9
soft_fail: false
2. OPA/Conftest Policy — Block MaxSessionDuration > Your Org Threshold
# policies/iam_session_duration.rego
package terraform.iam
max_allowed_duration := 14400 # 4 hours org policy
deny[msg] {
resource := input.resource.aws_iam_role[name]
resource.max_session_duration > max_allowed_duration
msg := sprintf(
"IAM role '%v' MaxSessionDuration %v exceeds org limit of %v seconds",
[name, resource.max_session_duration, max_allowed_duration]
)
}
3. AWS Config Rule — Continuous Compliance on Existing Roles
Deploy the managed rule iam-role-managed-policy-check or write a custom Config rule that evaluates MaxSessionDuration on all roles and fires an SNS alert + auto-remediation SSM document when the value exceeds your threshold.
4. Terraform Sentinel (HashiCorp Cloud Platform)
import "tfplan/v2" as tfplan
max_session := 14400
main = rule {
all tfplan.resource_changes as _, rc {
rc.type is "aws_iam_role" and rc.change.after.max_session_duration <= max_session
}
}
Enforce this as a hard-mandatory policy in your TFC/TFE workspace to block any terraform apply that sets an out-of-policy session duration.