Skip to content

manifest.py: a typo'd ProtectedAttribute 'disadvantaged' value silently inverts which group is disadvantaged #414

Description

@yakew7

Where: faircode/manifest.py:103,113 (ProtectedAttribute.disadvantaged_mask, numeric_threshold/age_interval_threshold branches).

The gap:

disadv = numeric < self.threshold if self.disadvantaged == "below" else numeric >= self.threshold

self.disadvantaged is compared against the exact string "below" with no validation anywhere that it's actually one of the two documented values ("below"/"above"). Any other value - "Below", "BELOW", a trailing space, a typo - silently takes the "above" branch instead of raising.

Repro:

>>> from faircode.manifest import ProtectedAttribute
>>> import pandas as pd
>>> pa = ProtectedAttribute(name="age", type="numeric_threshold", column="age", threshold=30, disadvantaged="Below")
>>> pa.disadvantaged_mask(pd.DataFrame({"age": [20, 30, 40]}))[0].tolist()
[False, True, True]

Intended (disadvantaged = below 30): [True, False, False]. A single capitalized letter in audit.yaml silently inverts which group the entire audit treats as disadvantaged, with zero error or warning.

Why it matters: this is a hand-written YAML field a contributor types directly (see faircode/MANIFEST_SPEC.md) - exactly the kind of value a typo reaches. For a fairness-auditing tool, silently swapping which group is "disadvantaged" produces a benchmark result that looks complete and plausible while being backwards.

Suggested fix: validate disadvantaged in ("below", "above") in ProtectedAttribute.__post_init__ (or wherever manifests are loaded from YAML), raising a clear error naming the bad value - mirroring the existing raise ValueError(f"unknown protected attribute type: {self.type!r}") pattern two lines below.

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

    bugSomething isn't workinghelp wantedExtra attention is needed

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions