What's Changed
[1.4.17] — 2026-08-14
Added
- CloudFormation —
AWS::Lambda::LayerVersionPermission— a stack that grants layer access (serverless-python-requirementsallowedAccounts, CDKaddPermission) failed withUnsupported resource typeand rolled back. The type now calls AddLayerVersionPermission,Refreturning<layer version ARN>#<statement id>. Layer policies also gained a realRevisionId(a stale one failsPreconditionFailedException), principal validation, and AWS's root-ARN statement shape. Contributed by @iot-rocket. - CloudWatch Logs —
GetLogGroupFields— returns field names found in recent stored events with a rough presence percent (logGroupFields: [{name, percent}]). HonorslogGroupNameorlogGroupIdentifier, optionaltime(±8 minutes) or the default last 15 minutes, system@*fields, and flattened JSON message keys. Contributed by @ovsteenb. - Step Functions —
aws-sdk:route53service integration — a Step Functions task calling the Route 53 SDK integration (e.g.ChangeResourceRecordSets) was unsupported. It now serializes the request through the rest-xml path and names an aws-sdk error the AWS way,Route53.<Error>Exception. Contributed by @bandle. - Step Functions —
States.Base64Encode/States.Base64Decodeintrinsics — the two intrinsic functions are implemented (UTF-8, the documented 10,000-character input cap, lenient decode padding); an over-cap or non-string argument fails the execution withStates.Runtime. Contributed by @bandle. - CloudFormation —
AWS::IoT::ThingType,AWS::IoT::Policy, andAWS::Cognito::IdentityPoolRoleAttachment— each type failed a stack withUnsupported resource typeand rolled it back; they now provision onto their own service (create/delete), so a stack declaring an IoT thing type or policy, or attaching roles to a Cognito identity pool, deploys cleanly. Reported by @iot-rocket.
Fixed
- API Gateway (HTTP API / v2) — custom Lambda (
REQUEST) authorizers are now invoked and enforced —_handle_execute_in_scopeonly branched onauth_type == "JWT", so a route with aCUSTOMauthorization type (the type a route gets when it references aREQUESTauthorizer) fell through unauthenticated: the authorizer Lambda was never invoked at all, regardless of whether the request carried a valid, invalid, or missing token. Adds a REQUEST-authorizer data-plane path mirroring the REST (v1) fix from 1.4.16 (_authorize_request_v1) — honorsauthorizerPayloadFormatVersion(1.0 IAM-policy-shaped event vs. 2.0),enableSimpleResponses({isAuthorized, context}) vs. IAM policy ({principalId, policyDocument, context}) response formats, andauthorizerResultTtlInSecondscaching — and populatesrequestContext.authorizer.lambdafor the downstream integration. Reported against real-world usage; the earlier REST (v1) authorizer fix covered v1 only. Contributed by @ryan-bennett. - EventBridge — API destination delivery no longer leaks credentials, and caller-supplied outbound values are validated — API destination requests now validate every caller-controlled value before it reaches the wire. (1) Delivery and OAuth token requests no longer follow redirects, preventing credentials from reaching another host;
3xxresponses are non-retryable failures. (2)InvocationEndpointand OAuthAuthorizationEndpointmust be dialablehttp(s)://URLs. The outbound opener also rejects non-HTTP(S) schemes, while loopback/private/link-local hosts remain allowed for the local emulator. (3)HttpMethodandAuthorizationTypeare validated against their API enums. (4)ApiKeyNamecan no longer override reserved headers. (5)DeauthorizeConnectionremoves authorization parameters, and delivery skips connections that are notAUTHORIZED. (6) OAuth token responses are capped at 1 MiB. Contributed by @t-rech. - Lambda — uncaught handler exceptions report
X-Amz-Function-Error: Unhandled— the Docker/RIE executor read the error class off a response header the RIE never sets, so every failure was reportedHandledand API Gateway consumers keying off the 502-for-Unhandled contract never took the error path. Headerless payloads are now classified by shape: the runtime's error serialization reportsUnhandled, an HTTP-style envelope withstatusCodestaysHandled. Contributed by @iot-rocket. - IoT —
CreateThingTypeis idempotent for identical re-creates — re-creating an existing thing type always returnedResourceAlreadyExistsException, so a retried request or a re-run provisioning script failed where AWS succeeds. The samethingTypePropertiesnow return the existing ids — absent,nulland empty compare equal,searchableAttributesis unordered — and only a real mismatch keeps the409, asCreateThingalready did. Contributed by @iot-rocket. - EC2 —
RevokeSecurityGroupIngress/RevokeSecurityGroupEgresshonourSecurityGroupRuleIds— both read onlyIpPermissions, so a revoke by rule id (as Terraform does) returnedReturn=truewhile removing nothing, leaving the rule in place forever. Ids now resolve against the group'ssgr-*rules, which are removed with their tags and echoed inrevokedSecurityGroupRuleSet; one unknown id rejects the whole call withInvalidSecurityGroupRuleId.NotFound. Contributed by @iot-rocket. - Cognito —
/oauth2/userInforeturns custom attributes and the plainusername— the response filtered attributes through a fixed standard-OIDC allowlist, droppingcustom:attributes; it now returns them (as AWS does foropenidandopenid profile), plus the plainusernameclaim alongsidecognito:username, andmiddle_name. Contributed by @rjmackay. - CloudFormation —
AWS::S3::BucketNotificationConfigurationis applied instead of silently dropped — the bucket provisioner read onlyBucketName/VersioningConfiguration, so aNotificationConfiguration(native, or expanded from a SAMEvents: S3trigger) reachedCREATE_COMPLETEwith no binding and S3 → Lambda/SQS/SNS/EventBridge never fired. It is now routed through the same pathPutBucketNotificationConfigurationtakes (create, update, and clear-on-remove), translating the CloudFormation property names to the S3 API's. Reported by @VictorAlejMadrid. - CloudFormation — stack metadata survives a
PERSIST_STATE=1restart — a stop/restore kept every provisioned resource butListStacks/DescribeStacks/ListExportscame back empty, because the stack records, events, exports, and change sets were never persisted. They are now saved and restored with the rest of the state. Reported by @iot-rocket. - S3 —
encoding-type=urlleaves the forward slash intact — key names,CommonPrefixes, and the echoedDelimiterpercent-encoded/as%2F, so a delimiter-collapsed "folder" listing was unreadable;/is now left alone while spaces and+are still encoded, matching S3. Reported by @gaul. - S3 — a delimited listing's
NextMarkeris the common prefix — when a page ended on aCommonPrefixesgroup,NextMarkerpointed at an underlying key rather than the prefix, so a client resuming from it re-walked keys it had already been told about as a prefix.NextMarkeris now the last row returned, and resuming skips the whole group. Reported by @gaul. - S3 —
CopyObjecthonours the copy-source date preconditions —x-amz-copy-source-if-modified-since/-if-unmodified-sincewere ignored (only the ETag conditions applied). Both are now evaluated with AWS's documented precedence (if-matchoverif-unmodified-since,if-none-matchoverif-modified-since), returning412 PreconditionFailedon a mismatch. Reported by @gaul. - S3 — a canned ACL expands to its group grants —
x-amz-aclatPutObject, and a cannedPutObjectAcl, stored only the owner'sFULL_CONTROL, sopublic-readreported no public grant. Canned ACLs now expand to the grants they imply (public-read→ AllUsersREAD,public-read-write→READ+WRITE,authenticated-read→ AuthenticatedUsersREAD), and an invalid canned value is rejected. Reported by @gaul. - S3 — a malformed
Content-MD5isInvalidDigest, notBadDigest— aContent-MD5that was not valid base64 or did not decode to 16 bytes returnedBadDigest, which AWS reserves for a well-formed digest that does not match the body; a malformed value now returnsInvalidDigest. Reported by @gaul. - S3 —
CompleteMultipartUpload'sLocationreflects the request host — theLocationwas built from a hard-codedhttp://localhost:4566, so it was wrong on any other port or host; it now echoes the endpoint the client reached. Reported by @gaul. - S3 —
PutObjectechoes the bucket's default encryption header — afterPutBucketEncryption, aPutObjectreply carried nox-amz-server-side-encryption, so a client could not confirm the object was encrypted as configured; the applied algorithm (AES256, oraws:kmswith its key id) is now stamped on the reply. Reported by @gaul.