Skip to content

effective_config guard blind spots, is_secret over-matching, and the JSON type change from redaction #289

Description

@fcostaoliveira

Three known limits in the effective_config guards and redactor added by #264. None is a live defect today; all are drift risk, and each is written down here rather than left implicit.

1. Guard 1 has two blind spots

no_production_code_reads_the_environment_outside_the_recorder is a substring scan. Two shapes evade it:

  • Braced import. use std::env::{var}; produces no use std::env::var substring, and the call site is then a bare var("X") with no env::var( prefix. Invisible.
  • env_var(&expr). Guard 2 counts non-literal env_var sites to pin the one legitimate dynamic caller, but excludes anything starting with & — so env_var(&name.to_uppercase()) is hidden from the dynamic count by the & exclusion and from the literal-name list by being non-literal. Invisible to both directions. The & exclusion has no current user and can probably just be dropped.

The real fix for both is to stop matching text: walk the token stream (or a syn parse) instead.

2. is_secret over-matches, and changes a JSON type

scrub_value replaces any leaf under a credential-named key with the string <redacted:set>, so a number becomes a string — session_pool_size: 8 → "<redacted:set>". A consumer that expects a number gets one only when the key happens not to match.

The marker list is contains over 13 substrings, so plausible-but-benign keys match: tokenizer (a real ES/OS analyzer key), password_policy, session_pool_size. And strip_userinfo's conservative fallback rewrites http://reporting.internal:8080/dashboards/team@ops → http://<redacted:set>@ops, destroying host, port and path.

Measured today: zero false positives across all 31 shipped configs and all 104 recorded knob names — every match is a genuine credential. The bias towards over-redaction is deliberate (a redacted knob costs provenance; a published one costs a rotation). But the type change deserves a decision: emit a typed placeholder, or keep the value's type and blank only strings.

3. Recording proves presence, not identity

effective_config::Recording is move-only and consumed by run_single_experiment, which makes a commented-out, conditional, or hoisted begin_experiment a compile error. It does not prove the token belongs to the experiment being run: handing run_single_experiment a token minted for a different (config, dataset) pair compiles and passes.

Closing that means carrying the config name and dataset in the token and checking it at the far end. The ordering half ("the recording begins before the engine is built") is covered by a source-scanning guard instead.

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

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions