Skip to main content

cdk-nag

PyPI version npm version Maven version NuGet version Go version

View on Construct Hub

Check CDK applications or CloudFormation templates for best practices using a combination of available rule packs. Inspired by cfn_nag.

Check out this blog post for a guided overview!

demo

Available Rules and Packs

See RULES for more information on all the available packs.

  1. AWS Solutions
  2. HIPAA Security
  3. NIST 800-53 rev 4
  4. NIST 800-53 rev 5
  5. PCI DSS 3.2.1
  6. Serverless

RULES also includes a collection of additional rules that are not currently included in any of the pre-built NagPacks, but are still available for inclusion in custom NagPacks.

Read the NagPack developer docs if you are interested in creating your own pack.

Usage

For a full list of options See NagPackProps in the API.md

Including in an application
from aws_cdk import App, Validations
from cdk_nag import AwsSolutionsChecks, NIST80053R5Checks

# CdkTestStack: Any

app = App()
CdkTestStack(app, "CdkNagDemo")
# Simple rule informational messages using the AWS Solutions Rule pack
Validations.of(app).add_plugins(AwsSolutionsChecks(app))
# Multiple rule packs can be run against the same app
Validations.of(app).add_plugins(NIST80053R5Checks(app))

Acknowledging a Rule

Use CDK's native Validations.of() API to acknowledge (suppress) rule violations on specific constructs.

Example 1) Acknowledging a rule on a construct
from aws_cdk.aws_ec2 import SecurityGroup, Vpc, Peer, Port
from aws_cdk import Stack, StackProps, Validations
from constructs import Construct

class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None, propertyInjectors=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation, propertyInjectors=propertyInjectors)
        test = SecurityGroup(self, "test",
            vpc=Vpc(self, "vpc")
        )
        test.add_ingress_rule(Peer.any_ipv4(), Port.all_traffic())
        Validations.of(test).acknowledge(
            id="AwsSolutions-EC23",
            reason="This security group is used for internal testing only."
        )
Example 2) Acknowledging a rule on a stack
from aws_cdk import App, Validations
from cdk_nag import AwsSolutionsChecks

# CdkTestStack: Any

app = App()
stack = CdkTestStack(app, "CdkNagDemo")
Validations.of(app).add_plugins(AwsSolutionsChecks(app))
Validations.of(stack).acknowledge(
    id="AwsSolutions-EC23",
    reason="All security groups in this stack are internal only."
)
Example 3) Acknowledging a specific finding

Certain rules report multiple findings per resource (e.g., IAM wildcard permissions). Each finding has its own ID in the format RuleId[FindingId].

If you received the following errors on synth/deploy:

[Error at /StackName/rUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Action::s3:*]: The IAM entity contains wildcard permissions.
[Error at /StackName/rUser/DefaultPolicy/Resource] AwsSolutions-IAM5[Resource::*]: The IAM entity contains wildcard permissions.

You can acknowledge a specific finding:

from aws_cdk.aws_iam import User, PolicyStatement
from aws_cdk import Stack, StackProps, Validations
from constructs import Construct

class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None, propertyInjectors=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation, propertyInjectors=propertyInjectors)
        user = User(self, "rUser")
        user.add_to_policy(
            PolicyStatement(
                actions=["s3:*"],
                resources=["*"]
            ))
        # Only acknowledge the s3:* action — Resource::* still triggers
        Validations.of(user).acknowledge(
            id="AwsSolutions-IAM5[Action::s3:*]",
            reason="Need s3:* for cross-account replication."
        )

Rules and Property Overrides

In some cases L2 Constructs do not have a native option to remediate an issue and must be fixed via Raw Overrides. Since raw overrides take place after template synthesis these fixes are not caught by cdk-nag. In this case you should remediate the issue and acknowledge the rule.

Example) Property Overrides
from aws_cdk.aws_ec2 import Instance, InstanceType, InstanceClass, MachineImage, Vpc, CfnInstance
from aws_cdk import Stack, StackProps, Validations
from constructs import Construct

class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None, propertyInjectors=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation, propertyInjectors=propertyInjectors)
        instance = Instance(self, "rInstance",
            vpc=Vpc(self, "rVpc"),
            instance_type=InstanceType(InstanceClass.T3),
            machine_image=MachineImage.latest_amazon_linux()
        )
        cfn_ins = instance.node.default_child
        cfn_ins.add_property_override("DisableApiTermination", True)
        Validations.of(instance).acknowledge(
            id="AwsSolutions-EC29",
            reason="Remediated through property override."
        )

Audit Trail: CloudFormation Metadata

By default, cdk-nag writes violations to CDK's policy-validation-report.json in the cloud assembly. If you need the v2-compatible cdk_nag metadata block in your synthesized CloudFormation templates (for existing compliance tooling), enable writeSuppressionsToCloudFormation:

from aws_cdk import App, Validations
from cdk_nag import AwsSolutionsChecks

app = App()
# Writes acknowledged rules into CfnResource Metadata as cdk_nag: { rules_to_suppress: [...] }
Validations.of(app).add_plugins(AwsSolutionsChecks(app, write_suppressions_to_cloud_formation=True))

This registers a WriteNagSuppressionsToCloudFormationAspect that runs during synthesis and copies Validations.of().acknowledge() data into the CloudFormation template Metadata section, preserving the same format as cdk-nag v2.

Using on CloudFormation templates

You can use cdk-nag on existing CloudFormation templates by using the cloudformation-include module.

Example) CloudFormation template

Sample App

from aws_cdk import App, Validations
from cdk_nag import AwsSolutionsChecks

# CdkTestStack: Any

app = App()
CdkTestStack(app, "CdkNagDemo")
Validations.of(app).add_plugins(AwsSolutionsChecks(app))

Sample Stack with imported template

from aws_cdk.cloudformation_include import CfnInclude
from aws_cdk import Stack, StackProps, Validations
from constructs import Construct

class CdkTestStack(Stack):
    def __init__(self, scope, id, *, description=None, env=None, stackName=None, tags=None, notificationArns=None, synthesizer=None, terminationProtection=None, analyticsReporting=None, crossRegionReferences=None, permissionsBoundary=None, suppressTemplateIndentation=None, propertyInjectors=None):
        super().__init__(scope, id, description=description, env=env, stackName=stackName, tags=tags, notificationArns=notificationArns, synthesizer=synthesizer, terminationProtection=terminationProtection, analyticsReporting=analyticsReporting, crossRegionReferences=crossRegionReferences, permissionsBoundary=permissionsBoundary, suppressTemplateIndentation=suppressTemplateIndentation, propertyInjectors=propertyInjectors)
        template = CfnInclude(self, "Template",
            template_file="my-template.json"
        )
        # Acknowledge rules on imported resources
        bucket = template.get_resource("rBucket")
        Validations.of(bucket).acknowledge(
            id="AwsSolutions-S1",
            reason="Logging not required for this bucket."
        )

Migrating from v2

cdk-nag v3 replaces the custom NagSuppressions API with CDK's native Validations.of().acknowledge() mechanism.

v2 v3
NagSuppressions.addResourceSuppressions(construct, [{ id, reason }]) Validations.of(construct).acknowledge({ id, reason })
NagSuppressions.addStackSuppressions(stack, [{ id, reason }]) Validations.of(stack).acknowledge({ id, reason })
NagSuppressions.addResourceSuppressionsByPath(stack, path, [...]) Validations.of(construct).acknowledge({ id, reason })
appliesTo: ['Action::s3:*'] id: 'AwsSolutions-IAM5[Action::s3:*]'
{ id: 'CdkNagValidationFailure', reason: '...' } Validations.of(construct).acknowledge({ id: 'RuleId', reason: '...' })

Note on bulk suppression: In v2, suppressing a rule without appliesTo would suppress all findings for that rule on the construct. In v3, each finding must be acknowledged individually (e.g., AwsSolutions-IAM5[Action::s3:*] and AwsSolutions-IAM5[Resource::*] are separate acknowledgments). Prefix matching (acknowledging AwsSolutions-IAM5 to suppress all findings) is not yet supported — tracked via [issue link].

Removed APIs:

  • NagSuppressions (use Validations.of().acknowledge())
  • INagSuppressionIgnore and all condition classes
  • NagPackSuppression interface
  • CdkNagValidationFailure concept
  • logIgnores and suppressionIgnoreCondition props

Contributing

See CONTRIBUTING for more information.

License

This project is licensed under the Apache-2.0 License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cdk_nag-3.0.2.tar.gz (735.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cdk_nag-3.0.2-py3-none-any.whl (732.8 kB view details)

Uploaded Python 3

File details

Details for the file cdk_nag-3.0.2.tar.gz.

File metadata

  • Download URL: cdk_nag-3.0.2.tar.gz
  • Upload date:
  • Size: 735.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.14.6

File hashes

Hashes for cdk_nag-3.0.2.tar.gz
Algorithm Hash digest
SHA256 c34f8128ac28368b34cb5d77ba21a5d541e652596d8ea844f608c0b76dc91f0d
MD5 ed3d621914f455c7e300ca5e71cc1d60
BLAKE2b-256 afa0bc4cb0b639c56ba1f5459ecbf2540597ee5af1afd7b79632548e165f6d14

See more details on using hashes here.

Provenance

The following attestation bundles were made for cdk_nag-3.0.2.tar.gz:

Publisher: release.yml on cdklabs/cdk-nag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cdk_nag-3.0.2-py3-none-any.whl.

File metadata

  • Download URL: cdk_nag-3.0.2-py3-none-any.whl
  • Upload date:
  • Size: 732.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.14.6

File hashes

Hashes for cdk_nag-3.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 861d8d30f5eb062d23462013bd6719fa355428f5525208b61f50da813065ea71
MD5 2d3cf71ec28e412a04eb9eb52dcc8925
BLAKE2b-256 7e2f5a0e2b20eccd6afb31f8214ddbcd981bac2ea624281d133cbb914235fa16

See more details on using hashes here.

Provenance

The following attestation bundles were made for cdk_nag-3.0.2-py3-none-any.whl:

Publisher: release.yml on cdklabs/cdk-nag

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

3.0.2

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page