Enforce AWS CDK security and compliance controls with cdk-nag. Use when adding rule packs, triaging findings, writing justified suppressions, integrating checks in CI/CD, or preventing insecure infrastructure patterns in CDK stacks.
Overall
score
100%
Does it follow best practices?
Validation for skill structure
Error: Cannot find name 'Key'
Cause: Missing or incorrect KMS import when creating encryption keys
Solution:
// ❌ Incorrect - missing import
const encryptionKey = new Key(this, 'EncryptionKey', {
enableKeyRotation: true,
});
// ✅ Correct - proper import
import * as kms from 'aws-cdk-lib/aws-kms';
const encryptionKey = new kms.Key(this, 'EncryptionKey', {
enableKeyRotation: true,
});Error: Cannot find module 'cdk-nag'
Solution:
# Install CDK Nag
npm install cdk-nag
# or
yarn add cdk-nagProper Import Syntax:
import { AwsSolutionsChecks, NagSuppressions } from 'cdk-nag';Error: Various construct-related import errors
Solution: Ensure proper CDK lib imports:
import { App, Aspects, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';Error: Rule ID doesn't exist or triggers incorrectly
Common Causes:
Debugging Steps:
// 1. Verify rule exists in current CDK Nag version
// Check: https://github.com/cdklabs/cdk-nag/blob/main/RULES.md
// 2. Remove suppression for non-existent rules
// ❌ Remove this if AwsSolutions-SNS2 doesn't exist
NagSuppressions.addResourceSuppressions(topic, [
{ id: 'AwsSolutions-SNS2', reason: 'Rule no longer exists' }, // Remove
{ id: 'AwsSolutions-SNS3', reason: 'SSL auto-enforced with KMS' }, // Keep
]);
// 3. Check rule pack documentation
// Some rules may be in compliance-specific packs (HIPAA, NIST, PCI)Issue: Rule triggers when it shouldn't
Investigation Steps:
Example - SNS SSL Enforcement:
// Rule AwsSolutions-SNS3 checks for SSL enforcement
// When KMS encryption is used, SSL is automatically enforced
const topic = new sns.Topic(this, 'Topic', {
masterKey: encryptionKey, // This auto-enforces SSL
});
// Suppression is appropriate here
NagSuppressions.addResourceSuppressions(topic, [
{
id: 'AwsSolutions-SNS3',
reason:
'SSL enforcement automatically applied when topic uses KMS encryption',
},
]);Error: Suppression path "/path/to/resource" did not match any resource
Cause: CDK Pipelines constructs are not guaranteed to be "visited" by Aspects during construction phase
Solution:
import {
CodePipeline,
CodePipelineSource,
ShellStep,
} from 'aws-cdk-lib/pipelines';
export class MyPipeline extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const pipeline = new CodePipeline(this, 'Pipeline', {
synth: new ShellStep('Synth', {
input: CodePipelineSource.gitHub('owner/repo', 'main'),
commands: ['npm ci', 'npm run build', 'npx cdk synth'],
}),
});
// ✅ CRITICAL: Force pipeline creation before suppressions
pipeline.buildPipeline();
// Now suppressions will work
NagSuppressions.addResourceSuppressionsByPath(
this,
'/MyPipeline/Pipeline/ArtifactsBucket/Resource',
[{ id: 'AwsSolutions-S1', reason: 'Pipeline artifacts bucket' }],
);
}
}Issue: Difficulty finding correct resource paths for suppressions
Solution: Use CDK synthesis to discover paths:
# Synthesize without suppressions to see violations
npx cdk synth
# Output will show exact paths:
# [Error at /MyStack/MyPipeline/Pipeline/ArtifactsBucket/Resource] AwsSolutions-S1
# Use the path in suppressions
NagSuppressions.addResourceSuppressionsByPath(
this,
'/MyStack/MyPipeline/Pipeline/ArtifactsBucket/Resource',
[{ id: 'AwsSolutions-S1', reason: 'Explanation' }]
);Issue: CDK Nag detects violations that L2 constructs don't expose properties to fix
Solution: Use raw CFN overrides and document with suppressions:
import { Instance, CfnInstance } from 'aws-cdk-lib/aws-ec2';
const instance = new Instance(this, 'Instance', {
// L2 construct doesn't expose termination protection
vpc: vpc,
instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.MICRO),
machineImage: MachineImage.latestAmazonLinux(),
});
// Apply raw override for features not in L2
const cfnInstance = instance.node.defaultChild as CfnInstance;
cfnInstance.addPropertyOverride('DisableApiTermination', true);
// Suppress and document the remediation
NagSuppressions.addResourceSuppressions(instance, [
{
id: 'AwsSolutions-EC29',
reason: 'Termination protection enabled via CFN property override',
},
]);Issue: Overrides applied after CDK Nag runs
Cause: CDK Nag runs during synthesis, property overrides may happen after
Solution: Ensure overrides are applied before synthesis completes:
// Apply overrides immediately after construct creation
const resource = new SomeResource(this, 'Resource', {});
const cfnResource = resource.node.defaultChild as CfnResource;
cfnResource.addPropertyOverride('SecurityProperty', true);
// Then apply suppressions
NagSuppressions.addResourceSuppressions(resource, [
{ id: 'Rule-ID', reason: 'Fixed via property override' },
]);Error: CDK Nag not scanning imported CloudFormation templates
Solution: Use CfnInclude correctly:
import { CfnInclude } from 'aws-cdk-lib/cloudformation-include';
export class ImportedStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Import template
const template = new CfnInclude(this, 'Template', {
templateFile: 'my-template.json',
});
// CDK Nag will scan the imported resources
// Add suppressions as needed
NagSuppressions.addResourceSuppressionsByPath(
this,
'/ImportedStack/Template/ResourceLogicalId',
[{ id: 'AwsSolutions-S1', reason: 'Explanation' }],
);
}
}Issue: Incorrect CloudFormation metadata format
❌ Incorrect:
{
"Metadata": {
"cdk-nag": {
// Wrong key format
"suppressions": [
// Wrong property name
{
"ruleId": "AwsSolutions-S1", // Wrong property name
"explanation": "Not needed" // Wrong property name
}
]
}
}
}✅ Correct:
{
"Metadata": {
"cdk_nag": {
"rules_to_suppress": [
{
"id": "AwsSolutions-S1",
"reason": "Access logging not required for internal bucket"
}
]
}
}
}Issue: CDK Nag causes synthesis to fail in CI/CD pipelines
Solution: Implement proper error handling:
# GitHub Actions example
- name: CDK Synthesis with Nag
run: |
npm run cdk -- synth
continue-on-error: false # Fail pipeline on violations
# Or allow failures in development
- name: CDK Synthesis with Nag (Dev)
run: |
npm run cdk -- synth || echo "CDK Nag violations found in dev"
continue-on-error: ${{ github.ref != 'refs/heads/main' }}Issue: Different behavior between local development and CI
Solution: Ensure consistent environment configuration:
// Use environment variables consistently
const environment = process.env.CDK_ENVIRONMENT || 'development';
const enableNag = process.env.ENABLE_CDK_NAG !== 'false';
if (enableNag) {
Aspects.of(app).add(new AwsSolutionsChecks());
}Issue: CDK Nag significantly slows down synthesis
Causes:
Solutions:
// 1. Environment-specific rule packs
if (process.env.NODE_ENV === 'production') {
Aspects.of(app).add(new AwsSolutionsChecks());
} else {
// Skip CDK Nag in development for faster iteration
}
// 2. Selective rule pack application
const complianceLevel = process.env.COMPLIANCE_LEVEL || 'basic';
Aspects.of(app).add(new AwsSolutionsChecks());
if (complianceLevel === 'full') {
// Only add additional packs when needed
Aspects.of(app).add(new HipaaSecurityChecks());
}Aspects.of(app).add(
new AwsSolutionsChecks({
verbose: true, // Enable detailed explanations
}),
);import { NagLogger } from 'cdk-nag';
class DebugLogger extends NagLogger {
onCompliance(data: any) {
console.log(`✅ PASS: ${data.resource} - ${data.ruleId}`);
}
onNonCompliance(data: any) {
console.log(
`❌ FAIL: ${data.resource} - ${data.ruleId}: ${data.ruleExplanation}`,
);
}
}
Aspects.of(app).add(
new AwsSolutionsChecks({
additionalLoggers: [new DebugLogger()],
}),
);# Generate construct tree for path debugging
npx cdk ls --long
# Synthesize with tree output
npx cdk synth --output cdk.out
# Examine construct tree
cat cdk.out/tree.json | jq '.tree.children'Issue: CDK Nag version incompatible with CDK version
Solution: Check compatibility matrix and upgrade both together:
# Check current versions
npm list aws-cdk-lib cdk-nag
# Upgrade both together
npm update aws-cdk-lib cdk-nagIssue: Rules added/removed/changed between versions
Solution: Review release notes when upgrading:
Install with Tessl CLI
npx tessl i pantheon-ai/cdk-nag@0.1.1