# Pulumi — CWE-407 Disclosure Brief
**2026-03-27 · Patch available — awaiting upstream merge**

## Finding

One O(P×R) defect in Pulumi's package info command, with four separate instances of the same pattern. `slices.Contains(Required, name)` is called inside a loop over all schema properties at four locations, producing quadratic behavior when rendering package documentation. Patched. Measured ratio: 114×.

## The Defects

**pulumi-0001 (PATCHED — HIGH):** `pkg/cmd/pulumi/packagecmd/package_info.go:333,367,451,474`

```go
// Four locations — per property name, check if required:
for _, name := range SortedKeys(Properties) {          // O(P) outer
    // ... line 333:
    if slices.Contains(schema.Required, name) { ... }  // O(R) scan
    // ... line 367:
    if slices.Contains(schema.Required, name) { ... }  // O(R) scan
    // ... line 451:
    if slices.Contains(Required, name) { ... }         // O(R) scan
    // ... line 474:
    if slices.Contains(Required, name) { ... }         // O(R) scan
}
// O(P × R) total per resource type — 4 separate scan sites
```

`slices.Contains(Required, name)` is called at four separate locations inside `for _, name := range SortedKeys(Properties)`. For P properties and R required-property names per resource type: **O(P × R)** total per resource type rendered. In a package with multiple resource types, this compounds. Fix: build a single `requiredSet map[string]bool` from `Required` once before the loop, replacing all four `slices.Contains` calls with O(1) map lookups. **Measured ratio: 114×.**

## Complexity Proof

Let P = len(Properties) = number of properties in the schema resource type, R = len(Required) = number of required property names, T = number of resource types in the package.

- Defective: 4 × O(R) scans per property name, O(P) properties per type, O(T) types.
  - Total comparisons: 4 × P × R × T.
- Fixed: one `map[string]bool` build per type (O(R)), then 4 × O(1) lookups per property.
  - Total: O(R × T) build + O(4 × P × T) lookups = O((R + P) × T).
- Speedup = 4PR / (R + P) ≈ 4P when R ≫ P, or 4R when P ≫ R.

At P=R=114 (114 properties, 114 required names, a realistic large resource schema):
- Defective: 4 × 114 × 114 = 51,984 comparisons per resource type.
- Fixed: 114 build + 4 × 114 = 570 operations per resource type.
- **114× measured ratio** (using P=R=114 as the measured configuration).

The pattern repeats identically at all four call sites (lines 333, 367, 451, 474), confirming the fix must be applied uniformly.

## Impact

All users of `pulumi package get-schema` and related `pulumi package` subcommands that trigger property rendering in `package_info.go`. This includes CI/CD pipelines that generate Pulumi SDKs from provider schemas, IDE integrations querying Pulumi schema information, and the Pulumi registry build process.

Large Pulumi providers — AWS, Azure, GCP — have resource types with hundreds of properties and required fields. The defect scales quadratically with schema size, making it worst for exactly the most-used providers.

Pulumi is the primary infrastructure-as-code platform for teams preferring general-purpose languages (TypeScript, Python, Go, .NET) over HCL.

## The Fix

Build `requiredSet` once before the property loop and replace all four `slices.Contains` calls:

```go
// Before (lines 333, 367, 451, 474 — same pattern at each site)
for _, name := range SortedKeys(Properties) {
    if slices.Contains(schema.Required, name) { ... }  // O(R) per property — 4 sites
}

// After
// CWE-407 fix: requiredSet map[string]bool built once for O(1) lookup at all 4 sites.
requiredSet := make(map[string]bool, len(schema.Required))
for _, r := range schema.Required {
    requiredSet[r] = true
}
for _, name := range SortedKeys(Properties) {
    if requiredSet[name] { ... }  // O(1) — applied at lines 333, 367, 451, 474
}
```

## Patch

`defects/pulumi/patch/pulumi-0001-package-info-required-set.patch`

Four-site patch confined to `pkg/cmd/pulumi/packagecmd/package_info.go`.

## What We Ask

1. Confirm receipt and assign a GitHub Security Advisory or issue reference (pulumi/pulumi).
2. Validate the patch against the package info and schema rendering test suites.
3. Assess CVE eligibility — pulumi-0001 measured at 114× with realistic large provider schemas.
4. Coordinate a disclosure date — we are targeting 90 days from first contact.

Contact: see cover email. This brief is confidential until coordinated disclosure.
