Skip to content

Image optimizer keys that collide after trimming resolve nondeterministically #1211

Description

@aram356

Description

ImageOptimizerSettings::normalize and ImageOptimizerProfileSet::normalize (crates/trusted-server-core/src/settings.rs) trim map keys by draining a HashMap and collecting it into a new one:

self.profiles = self
    .profiles
    .drain()
    .map(|(key, value)| (key.trim().to_string(), value.trim().to_string()))
    .filter(|(key, _)| !key.is_empty())
    .collect();

When two keys trim to the same name (for example medium and " medium"), the later entry overwrites the earlier one. HashMap iteration order is randomized per instance, so the surviving value is chosen at random on every parse. The same pattern applies to profile-set names in ImageOptimizerSettings::normalize.

Fastly parses Settings on every request, so one configuration can resolve the profile differently from request to request, and template_fingerprint (and therefore the template cache key) varies with it. This is the same class of problem as #1197, with a different cause.

Reproduction

[image_optimizer.profile_sets.default_images]
default_profile = "medium"

[image_optimizer.profile_sets.default_images.profiles]
medium = "width=100"
" medium" = "width=200"

Parsing this 64 times with Settings::from_toml returned both width=100 and width=200 for profiles["medium"] across parses.

Expected behavior

Keys that collide after trimming are rejected at load time with a configuration error naming the profile set and the colliding keys, for both profile names and profile-set names. Picking a winner deterministically would still silently drop one value.

Done when

  • Normalization rejects profile keys and profile-set keys that collide after trimming.
  • Regression tests cover both collision sites and the non-colliding case.

Affected area

Core (Edge Cookies, GDPR): settings loading / image optimizer

Version

Reproduced at a4e01eb55 (main).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions