diff --git a/packages/aws-cdk-lib/aws-iam/lib/policy-statement.ts b/packages/aws-cdk-lib/aws-iam/lib/policy-statement.ts index 5ee99ed959097..bfc8381e8f122 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/policy-statement.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/policy-statement.ts @@ -92,6 +92,7 @@ export class PolicyStatement { constructor(props: PolicyStatementProps = {}) { this._sid = props.sid; + this.validateStatementId(this._sid); this._effect = props.effect || Effect.ALLOW; this.addActions(...props.actions || []); @@ -117,6 +118,7 @@ export class PolicyStatement { */ public set sid(sid: string | undefined) { this.assertNotFrozen('sid'); + this.validateStatementId(sid); this._sid = sid; } @@ -232,6 +234,12 @@ export class PolicyStatement { } } + private validateStatementId(sid?: string) { + if (sid !== undefined && !cdk.Token.isUnresolved(sid) && !/^[0-9A-Za-z]*$/.test(sid)) { + throw new UnscopedValidationError(`Statement ID (sid) must be alphanumeric. Got '${sid}'. The Sid element supports ASCII uppercase letters (A-Z), lowercase letters (a-z), and numbers (0-9).`); + } + } + private validatePolicyActions(actions: string[]) { // In case of an unresolved list of actions return early if (cdk.Token.isUnresolved(actions)) return; diff --git a/packages/aws-cdk-lib/aws-iam/test/policy-statement.test.ts b/packages/aws-cdk-lib/aws-iam/test/policy-statement.test.ts index 322ac286e045a..a4883dda279cd 100644 --- a/packages/aws-cdk-lib/aws-iam/test/policy-statement.test.ts +++ b/packages/aws-cdk-lib/aws-iam/test/policy-statement.test.ts @@ -260,4 +260,28 @@ describe('IAM policy statement', () => { expect(mod).toThrow(/can no longer be modified/); } }); + + test('accepts valid alphanumeric sid', () => { + const validSids = ['ValidSid123', 'ALLCAPS', '123456', 'abc123DEF']; + + for (const sid of validSids) { + expect(() => new PolicyStatement({ sid })).not.toThrow(); + } + }); + + test('throws error when sid contains non-alphanumeric characters', () => { + const invalidSids = ['invalid-sid', 'with space', 'with_underscore', 'with.dot', 'with!special@chars']; + + for (const sid of invalidSids) { + expect(() => new PolicyStatement({ sid })) + .toThrow(`Statement ID (sid) must be alphanumeric. Got '${sid}'. The Sid element supports ASCII uppercase letters (A-Z), lowercase letters (a-z), and numbers (0-9).`); + } + }); + + test('throws error when setting sid to non-alphanumeric value', () => { + const statement = new PolicyStatement(); + + expect(() => statement.sid = 'invalid-sid') + .toThrow('Statement ID (sid) must be alphanumeric. Got \'invalid-sid\'. The Sid element supports ASCII uppercase letters (A-Z), lowercase letters (a-z), and numbers (0-9).'); + }); });