diff --git a/.projen/deps.json b/.projen/deps.json index 421c5c4b81..55fe56017b 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -2,7 +2,7 @@ "dependencies": [ { "name": "@aws-cdk/assert", - "version": "^2.11", + "version": "^2.18", "type": "build" }, { @@ -26,7 +26,7 @@ }, { "name": "aws-cdk-lib", - "version": "2.11.0", + "version": "2.18.0", "type": "build" }, { @@ -60,13 +60,12 @@ "type": "build" }, { - "name": "jest-junit", - "version": "^13", + "name": "jest", "type": "build" }, { - "name": "jest", - "version": "^27", + "name": "jest-junit", + "version": "^13", "type": "build" }, { @@ -109,7 +108,6 @@ }, { "name": "ts-jest", - "version": "^27", "type": "build" }, { @@ -118,7 +116,7 @@ }, { "name": "aws-cdk-lib", - "version": "^2.11.0", + "version": "^2.18.0", "type": "peer" }, { diff --git a/.projenrc.js b/.projenrc.js index 1ad4646e46..3cf04fc764 100644 --- a/.projenrc.js +++ b/.projenrc.js @@ -6,7 +6,7 @@ const { awscdk } = require('projen'); const project = new awscdk.AwsCdkConstructLibrary({ author: 'Arun Donti', authorAddress: 'donti@amazon.com', - cdkVersion: '2.11.0', + cdkVersion: '2.18.0', defaultReleaseBranch: 'main', majorVersion: 2, npmDistTag: 'latest', @@ -14,7 +14,7 @@ const project = new awscdk.AwsCdkConstructLibrary({ description: 'Check CDK v2 applications for best practices using a combination on available rule packs.', repositoryUrl: 'https://github.com/cdklabs/cdk-nag.git', - devDeps: ['@aws-cdk/assert@^2.11'], + devDeps: ['@aws-cdk/assert@^2.18'], publishToPypi: { distName: 'cdk-nag', module: 'cdk_nag', @@ -51,11 +51,6 @@ const project = new awscdk.AwsCdkConstructLibrary({ release: true, gitignore: ['.vscode'], }); -project.package.addField('resolutions', { - 'ansi-regex': '^5.0.1', - 'json-schema': '^0.4.0', - '@types/prettier': '2.6.0', -}); project.package.addField('prettier', { singleQuote: true, semi: true, diff --git a/RULES.md b/RULES.md index 0d9fb7a3ae..69fdd1da2b 100644 --- a/RULES.md +++ b/RULES.md @@ -98,6 +98,7 @@ The [AWS Solutions Library](https://aws.amazon.com/solutions/) offers a collecti | AwsSolutions-KDS1 | The Kinesis Data Stream does not has server-side encryption enabled. | Data is encrypted before it's written to the Kinesis stream storage layer, and decrypted after it’s retrieved from storage. This allows the system to meet strict regulatory requirements and enhance the security of system data. | | AwsSolutions-KMS5 | The KMS Symmetric key does not have automatic key rotation enabled. | KMS key rotation allow a system to set an yearly rotation schedule for a KMS key so when a AWS KMS key is required to encrypt new data, the KMS service can automatically use the latest version of the HSA backing key to perform the encryption. | | AwsSolutions-L1 | The non-container Lambda function is not configured to use the latest runtime version. | Use the latest available runtime for the targeted language to avoid technical debt. Runtimes specific to a language or framework version are deprecated when the version reaches end of life. This rule only applies to non-container Lambda functions. | +| AwsSolutions-LEX4 | Lex conversation logs are enabled and not encrypted with a KMS key. | You can use encryption to help protect the contents of your conversation logs. For text and audio logs, you can use AWS KMS customer managed CMKs to encrypt data in your CloudWatch Logs log group and S3 bucket. | | AwsSolutions-MS1 | The MediaStore container does not have container access logging enabled. | The container should have access logging enabled to provide detailed records for the requests that are made to the container. | | AwsSolutions-MS3 | The MediaStore container does not require requests to use SSL. | You can use HTTPS (TLS) to help prevent potential attackers from eavesdropping on or manipulating network traffic using person-in-the-middle or similar attacks. You should allow only encrypted connections over HTTPS (TLS) using the aws:SecureTransport condition on MediaStore container policies. | | AwsSolutions-MSK2 | The MSK cluster uses plaintext communication between clients and brokers. | TLS only communication secures data-in-transit by encrypting the connection between the clients and brokers. | diff --git a/package.json b/package.json index 60e7236875..bd4bd97302 100644 --- a/package.json +++ b/package.json @@ -39,12 +39,12 @@ "organization": false }, "devDependencies": { - "@aws-cdk/assert": "^2.11", + "@aws-cdk/assert": "^2.18", "@types/jest": "^26.0.24", "@types/node": "^14", "@typescript-eslint/eslint-plugin": "^5", "@typescript-eslint/parser": "^5", - "aws-cdk-lib": "2.11.0", + "aws-cdk-lib": "2.18.0", "constructs": "10.0.5", "eslint": "^8", "eslint-config-prettier": "^8.5.0", @@ -61,13 +61,13 @@ "json-schema": "^0.4.0", "npm-check-updates": "^12", "prettier": "^2.7.1", - "projen": "^0.58.17", + "projen": "^0.58.21", "standard-version": "^9", "ts-jest": "^27", "typescript": "^4.7.4" }, "peerDependencies": { - "aws-cdk-lib": "^2.11.0", + "aws-cdk-lib": "^2.18.0", "constructs": "^10.0.5" }, "keywords": [ @@ -142,15 +142,13 @@ "rootDir": "src" } }, - "resolutions": { - "ansi-regex": "^5.0.1", - "json-schema": "^0.4.0", - "@types/prettier": "2.6.0" - }, "prettier": { "singleQuote": true, "semi": true, "trailingComma": "es5" }, + "resolutions": { + "@types/prettier": "2.6.0" + }, "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." } \ No newline at end of file diff --git a/src/packs/aws-solutions.ts b/src/packs/aws-solutions.ts index 0cbff918f4..cce94f9caf 100644 --- a/src/packs/aws-solutions.ts +++ b/src/packs/aws-solutions.ts @@ -105,6 +105,7 @@ import { } from '../rules/kinesis'; import { KMSBackingKeyRotationEnabled } from '../rules/kms'; import { LambdaLatestVersion } from '../rules/lambda'; +import { LexBotAliasEncryptedConversationLogs } from '../rules/lex'; import { MediaStoreCloudWatchMetricPolicy, MediaStoreContainerAccessLogging, @@ -961,6 +962,15 @@ export class AwsSolutionsChecks extends NagPack { * @param ignores list of ignores for the resource */ private checkMachineLearning(node: CfnResource): void { + this.applyRule({ + ruleSuffixOverride: 'LEX4', + info: 'Lex conversation logs are enabled and not encrypted with a KMS key.', + explanation: + 'You can use encryption to help protect the contents of your conversation logs. For text and audio logs, you can use AWS KMS customer managed CMKs to encrypt data in your CloudWatch Logs log group and S3 bucket.', + level: NagMessageLevel.ERROR, + rule: LexBotAliasEncryptedConversationLogs, + node: node, + }); this.applyRule({ ruleSuffixOverride: 'SM1', info: 'The SageMaker notebook instance is not provisioned inside a VPC.', diff --git a/src/rules/index.ts b/src/rules/index.ts index 4c57bb2fb0..2c1e901831 100644 --- a/src/rules/index.ts +++ b/src/rules/index.ts @@ -30,6 +30,7 @@ export * as iam from './iam'; export * as kinesis from './kinesis'; export * as kms from './kms'; export * as lambda from './lambda'; +export * as lex from './lex'; export * as mediastore from './mediastore'; export * as msk from './msk'; export * as neptune from './neptune'; diff --git a/src/rules/lex/LexBotAliasEncryptedConversationLogs.ts b/src/rules/lex/LexBotAliasEncryptedConversationLogs.ts new file mode 100644 index 0000000000..4ad1b96349 --- /dev/null +++ b/src/rules/lex/LexBotAliasEncryptedConversationLogs.ts @@ -0,0 +1,91 @@ +/* +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ +import { parse } from 'path'; +import { CfnResource, Stack } from 'aws-cdk-lib'; +import { CfnBot, CfnBotAlias } from 'aws-cdk-lib/aws-lex'; +import { CfnLogGroup } from 'aws-cdk-lib/aws-logs'; +import { NagRuleCompliance, NagRules } from '../../nag-rules'; + +/** + * Lex Bot conversation logs are encrypted with KMS keys + * @param node the CfnResource to check + */ +export default Object.defineProperty( + (node: CfnResource): NagRuleCompliance => { + if (node instanceof CfnBotAlias || node instanceof CfnBot) { + const settingLocation = + node instanceof CfnBotAlias + ? node + : Stack.of(node).resolve(node.testBotAliasSettings); + const conversationLogSettings = Stack.of(node).resolve( + settingLocation?.conversationLogSettings + ); + if (conversationLogSettings !== undefined) { + const audioLogSettings = + Stack.of(node).resolve(conversationLogSettings.audioLogSettings) ?? + []; + for (const log of audioLogSettings) { + const resolvedLog = Stack.of(node).resolve(log); + if (Stack.of(node).resolve(resolvedLog.enabled) === true) { + const resolvedDestination = Stack.of(node).resolve( + resolvedLog.destination + ); + const s3Bucket = Stack.of(node).resolve( + resolvedDestination.s3Bucket + ); + const kmsKeyArn = Stack.of(node).resolve(s3Bucket.kmsKeyArn); + if (kmsKeyArn === undefined) { + return NagRuleCompliance.NON_COMPLIANT; + } + } + } + const textLogSettings = + Stack.of(node).resolve(conversationLogSettings.textLogSettings) ?? []; + for (const log of textLogSettings) { + const resolvedLog = Stack.of(node).resolve(log); + if (Stack.of(node).resolve(resolvedLog.enabled) === true) { + const resolvedDestination = Stack.of(node).resolve( + resolvedLog.destination + ); + const cloudwatch = Stack.of(node).resolve( + resolvedDestination.cloudWatch + ); + const logGroupLogicalId = NagRules.resolveResourceFromInstrinsic( + node, + cloudwatch.cloudWatchLogGroupArn + ); + let found = false; + for (const child of Stack.of(node).node.findAll()) { + if (child instanceof CfnLogGroup) { + if ( + logGroupLogicalId === + NagRules.resolveResourceFromInstrinsic(child, child.logicalId) + ) { + found = true; + if (child.kmsKeyId === undefined) { + return NagRuleCompliance.NON_COMPLIANT; + } + break; + } + } + } + if (!found) { + throw Error( + `Unable to find the CloudWatch Log group "${JSON.stringify( + logGroupLogicalId + )}" used in one of Text Log Destinations in the CDK Application. Therefore the rule could not be validated.` + ); + } + } + } + } + return NagRuleCompliance.COMPLIANT; + } else { + return NagRuleCompliance.NOT_APPLICABLE; + } + }, + 'name', + { value: parse(__filename).name } +); diff --git a/src/rules/lex/index.ts b/src/rules/lex/index.ts new file mode 100644 index 0000000000..ec40171149 --- /dev/null +++ b/src/rules/lex/index.ts @@ -0,0 +1,5 @@ +/* +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ +export { default as LexBotAliasEncryptedConversationLogs } from './LexBotAliasEncryptedConversationLogs'; diff --git a/test/Packs.test.ts b/test/Packs.test.ts index f96e7fde06..1b94b2afba 100644 --- a/test/Packs.test.ts +++ b/test/Packs.test.ts @@ -118,6 +118,7 @@ describe('Check NagPack Details', () => { 'AwsSolutions-KDS1', 'AwsSolutions-KMS5', 'AwsSolutions-L1', + 'AwsSolutions-LEX4', 'AwsSolutions-MS1', 'AwsSolutions-MS3', 'AwsSolutions-MSK2', diff --git a/test/rules/Lex.test.ts b/test/rules/Lex.test.ts new file mode 100644 index 0000000000..3509d29b76 --- /dev/null +++ b/test/rules/Lex.test.ts @@ -0,0 +1,263 @@ +/* +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ +import { Aspects, Stack } from 'aws-cdk-lib'; +import { Key } from 'aws-cdk-lib/aws-kms'; +import { CfnBot, CfnBotAlias } from 'aws-cdk-lib/aws-lex'; +import { LogGroup } from 'aws-cdk-lib/aws-logs'; +import { LexBotAliasEncryptedConversationLogs } from '../../src/rules/lex'; +import { validateStack, TestType, TestPack } from './utils'; + +const testPack = new TestPack([LexBotAliasEncryptedConversationLogs]); +let stack: Stack; + +beforeEach(() => { + stack = new Stack(); + Aspects.of(stack).add(testPack); +}); + +describe('Amazon Lex', () => { + describe('LexBotAliasEncryptedConversationLogs: Lex conversation logs are encrypted with KMS keys', () => { + const ruleId = 'LexBotAliasEncryptedConversationLogs'; + test('Noncompliance 1', () => { + new CfnBotAlias(stack, 'rBotAlias', { + botAliasName: 'foo', + botId: 'bar', + conversationLogSettings: { + audioLogSettings: [ + { + destination: { + s3Bucket: { + kmsKeyArn: 'foo', + s3BucketArn: 'bar', + logPrefix: 'baz', + }, + }, + enabled: true, + }, + { + destination: { + s3Bucket: { s3BucketArn: 'bar', logPrefix: 'baz' }, + }, + enabled: true, + }, + ], + }, + }); + validateStack(stack, ruleId, TestType.NON_COMPLIANCE); + }); + test('Noncompliance 2', () => { + new CfnBot(stack, 'rBot', { + dataPrivacy: {}, + idleSessionTtlInSeconds: 42, + name: 'foo', + roleArn: 'bar', + testBotAliasSettings: { + conversationLogSettings: { + audioLogSettings: [ + { + destination: { + s3Bucket: { + kmsKeyArn: 'foo', + s3BucketArn: 'bar', + logPrefix: 'baz', + }, + }, + enabled: true, + }, + { + destination: { + s3Bucket: { s3BucketArn: 'bar', logPrefix: 'baz' }, + }, + enabled: true, + }, + ], + }, + }, + }); + validateStack(stack, ruleId, TestType.NON_COMPLIANCE); + }); + test('Noncompliance 3', () => { + const logGroup = new LogGroup(stack, 'LogGroup', { + encryptionKey: undefined, + }); + new CfnBotAlias(stack, 'rBotAlias', { + botAliasName: 'foo', + botId: 'bar', + conversationLogSettings: { + textLogSettings: [ + { + destination: { + cloudWatch: { + cloudWatchLogGroupArn: logGroup.logGroupArn, + logPrefix: 'bar', + }, + }, + enabled: true, + }, + { + destination: { + cloudWatch: { cloudWatchLogGroupArn: 'foo', logPrefix: 'bar' }, + }, + enabled: false, + }, + ], + }, + }); + validateStack(stack, ruleId, TestType.NON_COMPLIANCE); + }); + test('Noncompliance 4', () => { + const logGroup = new LogGroup(stack, 'LogGroup', { + encryptionKey: undefined, + }); + new CfnBot(stack, 'rBot', { + dataPrivacy: {}, + idleSessionTtlInSeconds: 42, + name: 'foo', + roleArn: 'bar', + testBotAliasSettings: { + conversationLogSettings: { + textLogSettings: [ + { + destination: { + cloudWatch: { + cloudWatchLogGroupArn: logGroup.logGroupArn, + logPrefix: 'bar', + }, + }, + enabled: true, + }, + { + destination: { + cloudWatch: { + cloudWatchLogGroupArn: 'foo', + logPrefix: 'bar', + }, + }, + enabled: false, + }, + ], + }, + }, + }); + validateStack(stack, ruleId, TestType.NON_COMPLIANCE); + }); + test('Validation Failure 1 - using CloudWatch Log Group for text logs', () => { + new CfnBotAlias(stack, 'rBotAlias', { + botAliasName: 'foo', + botId: 'bar', + conversationLogSettings: { + textLogSettings: [ + { + destination: { + cloudWatch: { + cloudWatchLogGroupArn: LogGroup.fromLogGroupName( + stack, + 'Imported', + 'Imported' + ).logGroupArn, + logPrefix: 'bar', + }, + }, + enabled: true, + }, + ], + }, + }); + validateStack(stack, ruleId, TestType.VALIDATION_FAILURE); + }); + test('Compliance', () => { + new CfnBotAlias(stack, 'rBotAlias', { + botAliasName: 'foo', + botId: 'bar', + conversationLogSettings: { + audioLogSettings: [ + { + destination: { + s3Bucket: { + kmsKeyArn: 'foo', + s3BucketArn: 'bar', + logPrefix: 'baz', + }, + }, + enabled: true, + }, + { + destination: { + s3Bucket: { s3BucketArn: 'bar', logPrefix: 'baz' }, + }, + enabled: false, + }, + ], + }, + }); + const logGroup = new LogGroup(stack, 'LogGroup', { + encryptionKey: new Key(stack, 'Key'), + }); + new CfnBotAlias(stack, 'rBotAlias2', { + botAliasName: 'foo', + botId: 'bar', + conversationLogSettings: { + textLogSettings: [ + { + destination: { + cloudWatch: { + cloudWatchLogGroupArn: logGroup.logGroupArn, + logPrefix: 'bar', + }, + }, + enabled: true, + }, + ], + }, + }); + + new CfnBotAlias(stack, 'rBotAlias3', { + botAliasName: 'foo', + botId: 'bar', + }); + + new CfnBot(stack, 'rBot', { + dataPrivacy: {}, + idleSessionTtlInSeconds: 42, + name: 'foo', + roleArn: 'bar', + testBotAliasSettings: { + conversationLogSettings: { + audioLogSettings: [ + { + destination: { + s3Bucket: { + kmsKeyArn: 'foo', + s3BucketArn: 'bar', + logPrefix: 'baz', + }, + }, + enabled: true, + }, + ], + textLogSettings: [ + { + destination: { + cloudWatch: { + cloudWatchLogGroupArn: logGroup.logGroupArn, + logPrefix: 'bar', + }, + }, + enabled: true, + }, + ], + }, + }, + }); + new CfnBot(stack, 'rEmptyBot', { + dataPrivacy: {}, + idleSessionTtlInSeconds: 42, + name: 'foo', + roleArn: 'bar', + }); + validateStack(stack, ruleId, TestType.COMPLIANCE); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index 8345dcb810..8f5b1404f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,7 +10,7 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@aws-cdk/assert@^2.11": +"@aws-cdk/assert@^2.18": version "2.29.1" resolved "https://registry.yarnpkg.com/@aws-cdk/assert/-/assert-2.29.1.tgz#70a4541eb5d15e8ed1c244c29f6db82dbba71a1d" integrity sha512-qK+iuIFWxqKXrU537Y3rz2X0yraUB6/SiJ95i/qHUKJNJdYokhRl8fFyrA20lN+/AYZQ9NblDTaWPaN2ReyUPQ== @@ -1193,17 +1193,17 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -aws-cdk-lib@2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.11.0.tgz#a837f856d337db7dbc727bd718da8113e4596652" - integrity sha512-zN0K65oOAi5vedvRL9vXTQrYrpYO8rLCyajBpEKwi8z2D/rGUM9jnH1NHseUCJwQuP+I78FcUQgeFNPO80PUeg== +aws-cdk-lib@2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.18.0.tgz#a130edf9d90ec166d5c0f14d275ab49cbbe75261" + integrity sha512-4XpEqRgKSzDmcpeNGRqRlnWEltnt5+NoHWKpQDHUsAmyJ2QNQ5dYxVLIReaGiE9H8zS0rlpp3exuDEy0UgKj2Q== dependencies: "@balena/dockerignore" "^1.0.2" case "1.6.3" fs-extra "^9.1.0" ignore "^5.2.0" jsonschema "^1.4.0" - minimatch "^3.0.4" + minimatch "^3.1.2" punycode "^2.1.1" semver "^7.3.5" yaml "1.10.2" @@ -1421,9 +1421,9 @@ camelcase@^6.2.0, camelcase@^6.3.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001359: - version "1.0.30001359" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001359.tgz#a1c1cbe1c2da9e689638813618b4219acbd4925e" - integrity sha512-Xln/BAsPzEuiVLgJ2/45IaqD9jShtk3Y33anKb4+yLwQzws3+v6odKfpgES/cDEaZMLzSChpIGdbOYtH9MyuHw== + version "1.0.30001361" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001361.tgz#ba2adb2527566fb96f3ac7c67698ae7fc495a28d" + integrity sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ== case@1.6.3, case@^1.6.3: version "1.6.3" @@ -2058,9 +2058,9 @@ duplexer3@^0.1.4: integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA== electron-to-chromium@^1.4.172: - version "1.4.172" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.172.tgz#87335795a3dc19e7b6dd5af291038477d81dc6b1" - integrity sha512-yDoFfTJnqBAB6hSiPvzmsBJSrjOXJtHSJoqJdI/zSIh7DYupYnIOHt/bbPw/WE31BJjNTybDdNAs21gCMnTh0Q== + version "1.4.174" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.174.tgz#ffdf57f26dd4558c5aabdb4b190c47af1c4e443b" + integrity sha512-JER+w+9MV2MBVFOXxP036bLlNOnzbYAWrWU8sNUwoOO69T3w4564WhM5H5atd8VVS8U4vpi0i0kdoYzm1NPQgQ== emittery@^0.8.1: version "0.8.1" @@ -4105,9 +4105,9 @@ lru-cache@^6.0.0: yallist "^4.0.0" lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: - version "7.10.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.10.2.tgz#aab494e0768ce94f199ef553ffe0a362f2a58bb9" - integrity sha512-9zDbhgmXAUvUMPV81A705K3tVzcPiZL3Bf5/5JC/FjYJlLZ5AJCeqIRFHJqyBppiLosqF+uKB7p8/RDXylqBIw== + version "7.12.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.12.0.tgz#be2649a992c8a9116efda5c487538dcf715f3476" + integrity sha512-OIP3DwzRZDfLg9B9VP/huWBlpvbkmbfiBy8xmsXp4RPmE4A3MhwNozc5ZJ3fWnSg8fDcdlE/neRTPG2ycEKliw== make-dir@^3.0.0: version "3.1.0" @@ -4504,9 +4504,9 @@ npm-package-arg@^9.0.0, npm-package-arg@^9.0.1: validate-npm-package-name "^4.0.0" npm-packlist@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.0.tgz#f3fd52903a021009913a133732022132eb355ce7" - integrity sha512-a04sqF6FbkyOAFA19AA0e94gS7Et5T2/IMj3VOT9nOF2RaRdVPQ1Q17Fb/HaDRFs+gbC7HOmhVZ29adpWgmDZg== + version "5.1.1" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.1.tgz#79bcaf22a26b6c30aa4dd66b976d69cc286800e0" + integrity sha512-UfpSvQ5YKwctmodvPPkK6Fwk603aoVsf8AEbmVKAEECrfvL8SSe1A2YIwrJ6xmTHAITKPwwZsWo7WwEbNk0kxw== dependencies: glob "^8.0.1" ignore-walk "^5.0.1" @@ -4903,10 +4903,10 @@ progress@^2.0.3: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -projen@^0.58.17: - version "0.58.17" - resolved "https://registry.yarnpkg.com/projen/-/projen-0.58.17.tgz#0e5f0b723db94d275b4fd3c038b276a622502d61" - integrity sha512-dwVCHFB9cMDDn8ctJM/AXVHHabh+G+AbZ84kSOPo2uvpVdzTMkuJV/T/oXu+CDhkHCJQIfSh5zJ+7Ebpo5MGyg== +projen@^0.58.21: + version "0.58.21" + resolved "https://registry.yarnpkg.com/projen/-/projen-0.58.21.tgz#7549dd6ac38c70cca6e780129d3786cbfb3dfd85" + integrity sha512-Oai5QjuM4j3qfaOhErlllCJ8mSVKzyNft9aORhIwClfJCSJxdaJY0EeePjtt9wRocipCTzjL+IAEazwlP7iuGg== dependencies: "@iarna/toml" "^2.2.5" case "^1.6.3"