Skip to main content
Skip to main content

CDK Mixins Awareness

CDK Insights understands CDK Mixins โ€” the composable property-mutating API that ships with aws-cdk-lib. Findings are attributed to applied mixins automatically, and two template-level rules catch the specific footguns mixins introduce.

Why this matters

Mixins apply immediately at the .with() call site, before cdk synth runs. By the time the CloudFormation template is written, mixin-driven property changes are baked in โ€” and indistinguishable from properties set directly in construct props. That creates two new classes of bug that other tools don't catch:

Source code (what reviewers see)

// Bucket has versioning explicitly disabled in props
new s3.Bucket(this, 'Reports', { versioned: false });

Reality at synth (what AWS actually deploys)

// Source code reads the same โ€” but somewhere else in the app:
Mixins.of(stack).apply(new s3.mixins.BucketVersioning());

// Synth output now has versioning enabled. Code review lies.
// Without mixin awareness, "why is this enabled?" has no answer
// in the source.

Footgun #1 โ€” silent skip. Mixins.of(scope).apply(...) is silently skipped on constructs that don't support the mixin. Apply BucketEncryption to a stack with no buckets and nothing happens โ€” no warning, no synth failure.

Footgun #2 โ€” recursive application. .with(mixin) on a parent construct calls node.findAll() and applies the mixin to every descendant whose supports() returns true. A custom mixin without a supports() filter (the default returns true) gets applied to every resource type the parent contains.

What CDK Insights does about it

Per-Finding Mixin Attribution

Every finding tells you which mixins were applied to the resource โ€” built-in mixins by name, user-defined mixins surfaced as opaque (since aws-cdk-lib anonymises them).

Reads the aws:cdk:analytics:mixin manifest stream (zero source-scanning required)
Recommendations include a mixin-attribution sentence so fixes don't silently get undone at synth
Surfaces both vendored and user-defined mixin applications

Stack-Wide Compliance Audit

Detects when a compliance-critical mixin is applied to some-but-not-all resources of its target type โ€” the template-visible signature of a missing requireAll() enforcement.

Curated list of compliance-critical mixins (BucketEncryption, BucketVersioning, BucketBlockPublicAccess)
Fires per-resource so you see exactly which constructs are uncovered
Recommends switching to Mixins.of(scope).requireAll().apply(...) so synth fails on misses

Custom Mixin Review

Detects when a user-defined mixin appears on resources spanning 3+ distinct CFN types โ€” almost always a sign that .with() recursed through every descendant because the mixin's supports() filter accepts every construct.

Catches custom mixins that mutate resources you never intended
One per-stack finding (low noise, high signal)
Lists the affected resource types so you can narrow supports() correctly

Rules

RuleSeverityPillarFires whenRecommends
TL-MIXIN-001
Compliance-Critical Mixin Applied Without Stack Coverage
LOWSecurityWhen a compliance-critical mixin (e.g. BucketEncryption) is applied to some buckets but not others in the same stackSwitch to Mixins.of(scope).requireAll().apply(...) so synth fails when the mixin can't be applied to a selected construct
TL-MIXIN-002
Custom Mixin Applied Across Many Resource Types
LOWOperational ExcellenceWhen a user-defined mixin appears on 3+ distinct CFN resource types in the same stackVerify your custom mixin's supports() method narrows correctly to the intended resource type(s)

Enforcing mixins with requireAll()

The fix for the silent-skip footgun ships in aws-cdk-lib itself: requireAll() turns a silent skip into a hard synth error. CDK Insights TL-MIXIN-001 recommends this whenever it sees inconsistent compliance-critical mixin coverage.

import { Mixins } from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

// Without requireAll(): silently skips constructs that don't support
// the mixin. If your selector picks up no buckets, nothing happens.
Mixins.of(stack).apply(new s3.mixins.BucketEncryption());

// With requireAll(): synth FAILS when the mixin can't be applied to a
// selected construct. This is what cdk-insights TL-MIXIN-001 recommends
// for compliance-critical properties.
Mixins.of(stack)
  .requireAll()
  .apply(new s3.mixins.BucketEncryption());

Compatibility

  • aws-cdk-lib >= ~2.230 โ€” Mixins API in core. Older versions produce no mixin metadata; CDK Insights gracefully no-ops.
  • No peer-dependency bump required. CDK Insights still supports aws-cdk-lib >= 2.190.0; mixin features simply activate when the manifest contains the relevant metadata.
  • Built-in mixins are reported by FQN (e.g. aws-cdk-lib.aws_s3.mixins.BucketVersioning). User-defined mixins are anonymised by aws-cdk-lib to '*' for analytics privacy and surfaced as opaque.

See it in action

Run a scan against any stack that uses CDK Mixins โ€” mixin-attributed findings and the new TL-MIXIN-001 / TL-MIXIN-002 rules surface automatically.