Skip to content

sanitize: the egress guard is blind to WSL UNC paths, so diagnostics.py's fail-closed claim overreaches #512

Description

@pbean

sanitize's egress guard cannot see a path under a WSL UNC host, so the "final backstop" claim in diagnostics.py does not hold for that shape.

Measured

A diagnose document containing \\wsl.localhost\Ubuntu-24.04\home\u\p passes sanitize.assert_no_leak and returns []:

leaky = json.dumps({"env": {"raw_project": str(Path(r"\\wsl.localhost\Ubuntu-24.04\home\u\p"))}})
sanitize.assert_no_leak(leaky)   # -> []

Two independent causes:

  • _ABS_HOME_RE (src/bmad_loop/sanitize.py:100) matches /home/, /Users/, /root/ and [A-Za-z]:\Users\. A backslash \home\ under a UNC host matches none of them — and a WSL distro path ends in the Linux username, which is the identifier at risk.
  • The username rule compares getpass.getuser(), i.e. the Windows account. On a native-Windows interpreter reaching a distro path those two names are routinely different, so the rule cannot fire on the one it should.

Compounding it, when the document is rendered via json.dumps every backslash is doubled, so a raw-spelling substring scan over the rendered bytes never matches either — the trap already documented at src/bmad_loop/cli.py:3006-3011.

Why this matters now

Not currently exploitable: after #485, collect_env reduces the path to a boolean (diagnostics.py:295-296) and no EnvInfo field carries it. The problem is that the module docstring at diagnostics.py:14-20 describes the safety model as fail-closed "as a final backstop the rendered bytes are run through sanitize.guard" — and for this shape that backstop provably cannot fire. Any future field that carries a project path would leak the Linux username into a document people paste into bug reports, with the stated last line of defence silently absent. (collect_env's own docstring at diagnostics.py:262-266 states the limit correctly; the module header's blanket claim is the one that overreaches.)

Suggested

Teach the path rules the UNC/backslash form (\\wsl.localhost\<distro>\home\<user>, \\wsl$\..., and the \\?\UNC\ folding is_wsl_unc_path already normalizes at src/bmad_loop/platform_util.py:163), and reconcile the module docstring with what the guard actually covers. A regression test should assert over decoded values rather than rendered bytes, for the escaping reason above.

Surfaced while reviewing #485; the vacuous test assertions that hid it were fixed there in 03ac27e, but the guard's blindness is upstream of that and unfixed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions