Skip to main content
HIGHCross-serviceSecurity

Cross-Resource Misconfiguration

cross-resource-misconfiguration

What this rule checks

Detects misconfigurations only visible across multiple resources: Lambda functions referencing VPC-only resources without VpcConfig, S3 replication without encryption configuration, and security groups exposing non-standard ports to the public when used by sensitive services.

How to fix it

  1. 1Configure VpcConfig on Lambda functions that reach VPC-only resources (RDS, ElastiCache, Redshift, OpenSearch, ECS Service)
  2. 2Specify EncryptionConfiguration on S3 replication rules so replicated objects retain encryption at the destination
  3. 3Restrict 0.0.0.0/0 ingress on non-standard ports for security groups attached to sensitive services
FlaggedThe Lambda references the VPC-only RDS endpoint (via an environment variable / Fn::GetAtt dependency) but has no VpcConfig, so it can never reach the database — the cross-resource check fires.
import { SecretValue } from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as rds from 'aws-cdk-lib/aws-rds';

const vpc = new ec2.Vpc(this, 'Vpc', {
  maxAzs: 2,
  natGateways: 0,
  subnetConfiguration: [
    { name: 'isolated', subnetType: ec2.SubnetType.PRIVATE_ISOLATED, cidrMask: 24 },
  ],
});
const db = new rds.DatabaseInstance(this, 'Db', {
  engine: rds.DatabaseInstanceEngine.postgres({
    version: rds.PostgresEngineVersion.VER_16_4,
  }),
  vpc,
  vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
  credentials: rds.Credentials.fromPassword(
    'admin',
    SecretValue.unsafePlainText('SuperSecretPassw0rd!'),
  ),
});
// Lambda references the VPC-only database but is NOT VPC-enabled, so it can
// never reach it.
new lambda.Function(this, 'Fn', {
  runtime: lambda.Runtime.NODEJS_22_X,
  handler: 'index.handler',
  code: lambda.Code.fromInline('exports.handler = async () => {};'),
  environment: {
    DB_HOST: db.dbInstanceEndpointAddress,
  },
});
FixedThe Lambda now runs inside the VPC (vpc + isolated subnets) and its security group is allowed to the database port, so the connectivity mismatch is resolved and no cross-resource finding is emitted.
import { SecretValue } from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as rds from 'aws-cdk-lib/aws-rds';

const vpc = new ec2.Vpc(this, 'Vpc', {
  maxAzs: 2,
  natGateways: 0,
  subnetConfiguration: [
    { name: 'isolated', subnetType: ec2.SubnetType.PRIVATE_ISOLATED, cidrMask: 24 },
  ],
});
const db = new rds.DatabaseInstance(this, 'Db', {
  engine: rds.DatabaseInstanceEngine.postgres({
    version: rds.PostgresEngineVersion.VER_16_4,
  }),
  vpc,
  vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
  credentials: rds.Credentials.fromPassword(
    'admin',
    SecretValue.unsafePlainText('SuperSecretPassw0rd!'),
  ),
});
// Lambda runs inside the VPC and its security group can reach the database.
const fn = new lambda.Function(this, 'Fn', {
  runtime: lambda.Runtime.NODEJS_22_X,
  handler: 'index.handler',
  code: lambda.Code.fromInline('exports.handler = async () => {};'),
  vpc,
  vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
  environment: {
    DB_HOST: db.dbInstanceEndpointAddress,
  },
});
db.connections.allowDefaultPortFrom(fn);

CDK Insights pinpoints the exact file and line in your CDK source for every finding, so you can jump straight to the fix.

Affected resource types

AWS::Lambda::FunctionAWS::S3::BucketAWS::EC2::SecurityGroupAWS::RDS::DBInstanceAWS::ElastiCache::CacheClusterAWS::Redshift::ClusterAWS::OpenSearchService::DomainAWS::Elasticsearch::Domain

Compliance frameworks

SOC2HIPAAPCI-DSSNIST

AWS documentation

Read the AWS guidance

Intentional? Suppress this finding

Sometimes a flag is deliberate — a genuinely public endpoint, say. You can dismiss cross-resource-misconfiguration and the reason is kept in the report, not silently hidden.

In .cdk-insights.json:

{
  "ignoreRules": [
    { "id": "cross-resource-misconfiguration", "reason": "Why this is intentional" }
  ]
}

Or inline in your CDK code:

Validations.of(scope).acknowledge({
  id: 'cdk-insights::cross-resource-misconfiguration',
  reason: 'Why this is intentional',
});

Use the rule ID cross-resource-misconfiguration shown above — not the CDK-* ID from SARIF / GitHub code scanning. To dismiss every finding on one construct instead, use ignorePaths. Suppression docs →

Catch this in your stack

$ npx cdk-insights scan

CDK Insights runs this and 118+ other rules locally against your synthesised CDK app — free, no account, your code never leaves your machine.

More Cross-service rules