Skip to content

Low-severity residues from the .ashpkg hardening review: a drifted second escaper, truncated refusal guidance, chardev 500 #492

Description

@IanFrelinger

Three low-severity residues from the round-5 adversarial review, kept out of #491 to avoid widening a PR that had already been through five rounds. All were reproduced; all were downgraded to LOW by every skeptic who adjudicated them.

1. A second, drifted copy of the escaper

ashlar mesh lan prints an unauthenticated LAN beacon's name to the terminal. Both guards on that path — MeshBeacon.TryParse (MeshDiscoveryService.cs:78) and ExecuteLan's safeName (MeshCommand.cs:339) — filter with char.IsControl, which is UnicodeCategory.Control (Cc) only. That misses U+200E/200F, U+202A–202E and U+2066–2069, so a beacon name carrying a bidi override reaches the operator's terminal (reproduced: the e2 80 ae byte sequence emitted once).

The interesting part is not the severity, it's the shape: UntrustedText's own doc comment says it exists so there is one escaper rather than several that drift. This is the drift, already present. Worth routing mesh lan through UntrustedText.ForConsole — which handles bidi overrides — rather than keeping a second hand-rolled filter.

2. Truncation can cut the load-bearing tail off a refusal

UntrustedText.ForConsole's 2,000-char bound truncates after the sender-chosen portion, so a long symlink target can push "not a regular file" and the remediation sentence off the end of SafePackageRead's symlink refusal. The operator is told a link was refused and loses the part explaining what to do instead.

Fix is to bound the sender-chosen component rather than the composed message, so the fixed guidance always survives.

3. A character device is a 500, not the promised 404

A character-device node in the published directory passes every Unix gate: advertised in /mesh/v1/index as a 0-byte package, and GET returns HTTP 500 rather than the 404 the code's own comment promises for a refusal. No content leaks and nothing hangs — it is a wrong status code and a comment that overstates.

Residual noted on #488

A hard link (not a symlink) to a file the daemon can read still serves, since a hard link has no LinkTarget and is a regular file. Three skeptics independently judged the capability delta ~zero — creating one needs write access to the published directory, and hard links cannot cross filesystems — so it did not block #491. Recording it because the reasoning depends on the daemon and the planting user being the same principal, which is an assumption worth revisiting if the daemon ever runs more privileged than the share's writers.

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 working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions