cdk-nag
Checks AWS CDK apps and CloudFormation templates against AWS Solutions, NIST, HIPAA, and PCI-DSS rule packs so non-compliant resources get caught before deployment.
Repository Health
Technical Analysis
cdk-nag is a validation library for AWS CDK applications that scans the synthesized construct tree for resources that violate common security and compliance best practices. Rather than reviewing CloudFormation output by hand or waiting for a separate security-scanning stage, teams register one or more NagPacks directly on their CDK app — AWS Solutions, NIST 800-53 (rev 4/5), HIPAA Security, PCI DSS 3.2.1, or Serverless — and get findings surfaced as CDK validation errors or warnings at synth time.
Each pack is built from a large library of individually testable rule functions organized by AWS service (S3, IAM, RDS, Lambda, EKS, and roughly 40 more), so the same rule logic can be reused across packs and extended for custom compliance frameworks. Violations can be acknowledged per-resource using CDK’s own native Validations acknowledgment API, keeping suppressions in the same place as the infrastructure code they apply to instead of a separate config file.
What You Get
- Six ready-made rule packs — AWS Solutions, NIST 800-53 rev 4, NIST 800-53 rev 5, HIPAA Security, PCI DSS 3.2.1, and Serverless — covering roughly 150 individual checks across ~40 AWS services
- A
NagPackbase class and per-service rule function convention for authoring custom rule packs on top of the same engine - Native integration with CDK’s
Validations.of(app).addPlugins()API, so multiple packs can be layered on one app with no bespoke wiring - Per-resource rule acknowledgment (suppression) using CDK’s own metadata mechanism, with an optional aspect to mirror suppressions into synthesized CloudFormation metadata for audit trails
- Support for checking either a live CDK construct tree or exported CloudFormation templates directly
- Multi-language distribution via jsii — the same rule packs are published to npm, PyPI, Maven, NuGet, and Go
Common Use Cases
- Blocking a CI pipeline when a CDK stack provisions an S3 bucket, IAM role, or security group that violates an org’s AWS Solutions baseline
- Proving HIPAA Security or PCI DSS 3.2.1 alignment for regulated workloads as part of a compliance audit trail
- Adding NIST 800-53 checks to government or public-sector CDK deployments without hand-writing custom policy-as-code
- Reviewing CloudFormation templates produced outside of CDK (e.g. from a third-party IaC tool) against the same rule packs
- Building an internal, organization-specific NagPack on top of cdk-nag’s rule-authoring conventions for rules not covered by the built-in packs
Under The Hood
Architecture
cdk-nag is a layered, modular system built around an abstract NagPack base class (src/nag-pack.ts) that implements aws-cdk-lib’s IPolicyValidationPlugin interface. NagPack.validateScope() walks the construct tree looking for CfnResource nodes and delegates to a subclass’s checkResource() implementation; each concrete pack (src/packs/aws-solutions.ts, hipaa-security.ts, nist-800-53-r4.ts, nist-800-53-r5.ts, pci-dss-321.ts, serverless.ts) composes dozens of independent rule functions imported from src/rules/<service>/ (s3, iam, rds, lambda, eks, and ~35 more service directories) via applyRule(), which groups violations by rule ID and checks CDK’s own ACKNOWLEDGED_RULES_METADATA_KEY metadata up the construct scope chain before reporting. If the NagPack/applyRule contract changes, every pack and every one of its ~150 rule functions is affected, but the converse isn’t true — individual rule functions in src/rules/ are self-contained and can be added, removed, or reused across packs without touching the base engine.
Tech Stack Written in TypeScript (jsii 6.x, TypeScript 6.x) and packaged via jsii-pacmak so the same source compiles to npm, PyPI, Maven, NuGet, and Go artifacts from one codebase. The project is scaffolded and maintained with projen (cdklabs-projen-project-types), which generates package.json scripts, CI workflows, and release automation rather than hand-maintained config. Peer dependencies are aws-cdk-lib ^2.257.0 and constructs ^10.5.1; jsii-rosetta compiles the README’s TypeScript code samples so they stay in sync with the actual API across all published languages.
Code Quality
The test suite (test/rules/, test/utils/) mirrors the src/rules/ structure with 49 test files, run under Jest with ts-jest and coverage collection enabled across json/lcov/clover/cobertura reporters. Rule functions follow a strict, consistent shape — a named function bound via Object.defineProperty (working around arrow functions lacking a configurable name, needed for jsii interop) that returns a NagRuleCompliance or a findings array — and error handling is explicit: applyRule() catches thrown errors and reports them as violations rather than swallowing them silently. GitHub Actions workflows (build.yml, pull-request-lint.yml, dependency-review.yml, release.yml) gate merges and automate semantic-versioned releases via commit-and-tag-version.
API Design
The public surface is deliberately tiny: adding a rule pack to a CDK app is a single Validations.of(app).addPlugins(new AwsSolutionsChecks(app)) call, and multiple packs can be stacked on the same app with no extra configuration. Suppressions reuse CDK’s own native acknowledgment API instead of introducing a parallel suppression format, and a verbose flag toggles between terse and fully-explained violation messages. RULES.md documents every rule with its pack membership, and API.md is generated directly from the TypeScript source via jsii-docgen, keeping documentation and implementation from drifting apart.