java-topology/defects/micronaut/patch/micronaut-0003-environmentpropertysource-includes-excludes-contains.md

2.6 KiB
Raw Permalink Blame History

UNDF: UNDF-2026-000000463

micronaut-0003: EnvironmentPropertySource — O(E×N) includes/excludes.contains in env loop

CWE-407 — Algorithmic Complexity: Linear Membership Test in Loop

Field Value
ID micronaut-0003
Severity LOW
Ecosystem micronaut-core
Package micronaut-inject
File inject/src/main/java/io/micronaut/context/env/EnvironmentPropertySource.java
Lines 89, 92
Complexity O(E × N) where E = environment variable count, N = includes/excludes list size
Fix Convert includes and excludes parameters from List<String> to Set<String> at call sites

Description

getEnv(Map<String,String> env, List<String> includes, List<String> excludes) iterates over all environment variables (E entries) and for each calls excludes.contains(envVar) and includes.contains(envVar) — both O(N) on List<String> parameters.

for (Map.Entry<String, String> entry : env.entrySet()) {   // O(E)
    String envVar = entry.getKey();
    if (excludes != null && excludes.contains(envVar)) {   // O(N) List scan
        continue;
    }
    if (includes != null && !includes.contains(envVar)) {  // O(N) List scan
        continue;
    }
    ...
}

With E=500 env vars and N=50 includes/excludes: 500 × 50 × 2 = 50,000 operations vs 500 × 2 = 1,000.

Impact

Called during application context initialization and every time the environment is refreshed. In containerized environments with hundreds of env vars (Kubernetes, Docker) and Micronaut applications using many env var filters, this creates unnecessary O(E×N) startup overhead.

Fix

// Change signature to accept Set<String> (or convert internally)
static Map getEnv(Map<String, String> env,
                  @Nullable Collection<String> includes,
                  @Nullable Collection<String> excludes) {
    // Convert to Set at entry point if caller passes List
    Set<String> excludeSet = excludes instanceof Set ? (Set<String>) excludes
                              : (excludes != null ? new HashSet<>(excludes) : null);
    Set<String> includeSet = includes instanceof Set ? (Set<String>) includes
                              : (includes != null ? new HashSet<>(includes) : null);
    for (Map.Entry<String, String> entry : env.entrySet()) {
        if (excludeSet != null && excludeSet.contains(envVar)) { continue; } // O(1)
        if (includeSet != null && !includeSet.contains(envVar)) { continue; } // O(1)
        ...
    }
}

Speedup Estimate

At E=500, N=50: 50x speedup per environment resolution call.