Skip to content

datadog-cdk-constructs-v2 reads aws-cdk-lib's **private** Function.environment internals — it broke cdk synth once (2.253.0), and the "fix" dug deeper instead of respecting the interface #620

Description

@ahammond

Summary

This library reaches into aws-cdk-lib's private Function.environment field — and, since v4.0.0, into the private .map backing store of the internal Box that field now holds. The code's own comments admit it: "AWS does not expose the environment field" and "cast to any to access the private environment fields." It does so anyway.

That is the whole bug. A routine, semver-compatible aws-cdk-lib minor (2.252 → 2.253) changed the field's internal shape and broke cdk synth for every stack using the default sourceCodeIntegration (#596). The v4.0.0 "fix" did not remove the illegal access — it re-pointed it at the deeper new internal and raised the peer floor, then closed the follow-on breakage as the user's fault (#606). It will break again on the next refactor.

The defect (current main)

src/env.ts#L67 and #L124:

lam.environment.map.get(DD_TAGS)?.value          // setGitEnvironmentVariables
lam_with_env_vars.environment.map.get(envVar)    // applyEnvVariables

environment is and always has been private. aws-cdk-lib's public contract for env vars is Function.addEnvironment(key, value) — which this library already uses to write. The breakage exists only because it also reads across the private boundary.

aws-cdk-lib Function.environment
≤ 2.252.0 private environment: { [key]: EnvironmentConfig } = {};
≥ 2.253.0 private readonly environment: IMapBox<…> = Box.fromMap(new Map());

(Verified at aws-cdk tags v2.252.0 / v2.253.0.)

The correct fix

  1. Respect the interface. Stop reading the private field. This library is the sole writer of DD_TAGS and the DD_* defaults on these paths, so it can track its own writes (a WeakMap<Function, …>) instead of interrogating aws-cdk-lib's private state.
  2. Extend the interface, properly. For the one case that benefits from reading user-set values, aws-cdk-lib has no public accessor yet — but it is open source and accepts contributions (aws/aws-cdk). Adding a supported hasEnvironment(key) / read-only getter is a small, routine, mergeable PR. The right path was always: collaborate upstream to add the public API, then depend on it. Reaching into Box.map instead — and, when that broke, reaching in further rather than opening that PR — reflects either a lack of diligence or a lack of competence, not a genuine constraint. There was a correct option available the entire time and it was not taken.

Affected versions

Repro / impact

sourceCodeIntegration is on by default, so a transitive aws-cdk-lib bump to 2.253.0 turned cdk synth into a hard failure for downstream stacks (≤3.12.0):

TypeError: Cannot read properties of undefined (reading 'value')
    at setGitEnvironmentVariables (env.js)
    at DatadogLambda.addLambdaFunctions (datadog-lambda.js)

The only workarounds were disabling a default Datadog feature or pinning aws-cdk-lib. v4.0.0 converted this into a permanent peer constraint and a recurring fragility. Removing the dependency on private internals eliminates the entire class of failure.

This is also being raised with our Datadog account team. For a library published under the Datadog name that instruments production fleets by default, depending on a dependency's private internals — when a supported public path exists and a clean upstream extension was available — is below the standard we expect. We're asking for the root-cause fix, not another patch that re-points the same illegal access.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions