(aws-cognito): domainPrefix validation is looser than the documented Domain constraint
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
`UserPoolDomain` validates `cognitoDomain.domainPrefix` against `/^[a-z0-9-]+$/`.
The documented constraint for `AWS::Cognito::UserPoolDomain.Domain` is narrower: pattern `^[a-z0-9](?:[a-z0-9\-]{0,61}[a-z0-9])?$`, minimum length 1, maximum length 63.
CDK's pattern accepts everything the documented one does and more, so a few shapes pass synth and get written into the template unchanged:
- a leading hyphen, `-myprefix`
- a trailing hyphen, `myprefix-`
- hyphens only, `---`
- anything longer than 63 characters
The check in `packages/aws-cdk-lib/aws-cognito/lib/user-pool-domain.ts` is the only synth-time validation the prefix gets, and the value flows straight through to the L1 `Domain` property.
### Expected Behavior
Synth fails for a prefix the documented pattern rejects, the same way it already does for an uppercase or underscore-bearing one.
### Current Behavior
Synth succeeds and the value lands in the template as written:
```
leading hyphen | SYNTH OK | Domain="-myprefix"
trailing hyphen | SYNTH OK | Domain="myprefix-"
all hyphens | SYNTH OK | Domain="---"
length 64 | SYNTH OK | Domain="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
control (valid) | SYNTH OK | Domain="valid-prefix-123"
control (uppercase) | THREW | domainPrefix for cognitoDomain can contain only lowercase alphabets, numbers and hyphens
```
The uppercase control is there to confirm validation actually runs, so these four are getting through the check rather than skipping it.
### Reproduction Steps
```ts
import { App, Stack } from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import * as cognito from 'aws-cdk-lib/aws-cognito';
for (const prefix of ['-myprefix', 'myprefix-', '---', 'a'.repeat(64)]) {
const stack = new Stack(new App(), 'S');
const pool = new cognito.UserPool(stack, 'Pool');
// expected: throws, since the documented pattern rejects all four
// actual: synthesizes, and the value lands in the template unchanged
pool.addDomain('Domain', { cognitoDomain: { domainPrefix: prefix } });
console.log(prefix, JSON.stringify(Template.fromStack(stack).toJSON().Resources));
}
```
### Possible Solution
Match the documented constraint:
```ts
!/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(props.cognitoDomain.domainPrefix)
```
That covers the length bound too, so it needs no separate check, and it keeps the existing error code. The message would want rewording, since "can contain only lowercase alphabets, numbers and hyphens" no longer describes what is being enforced.
On backwards compatibility, AGENTS.md draws the line at whether the input ever deployed. These values do not appear deployable, so by that rule this is the no-feature-flag case and failing fast at synth is preferred. That is worth a maintainer's read rather than my assumption, given the caveat below.
Happy to open a PR if this is something you want fixed.
### Additional Information/Context
Two things worth flagging so nobody takes more from this than it supports.
The pattern and the length bound live in the CloudFormation documentation. The resource schema published at `schema.cloudformation.us-east-1.amazonaws.com/aws-cognito-userpooldomain.json` types `Domain` as a plain string with no pattern and no bounds, so the rejection is presumably Cognito rather than CloudFormation validating client-side. I have not deployed any of these, so treat "these are invalid" as coming from the documentation rather than from a failed deploy I watched.
This is also not an explanation for #37514. That one is about tokens, and every value here is static.
### AWS CDK Library version (aws-cdk-lib)
2.264.0
### AWS CDK CLI version
2.1131.0
### Node.js Version
v24.12.0
### OS
Windows 11 Pro 10.0.26200
### Language
TypeScript
Contributor guide
Assessment
This issue has not been assessed yet.