Skip to content

Treat the tree the runner walks as untrusted input #61

Description

@iderex

Everything under experiments/ is written by whoever proposes an experiment, and
the runner walks it. That makes the tree the runner's input rather than its
environment, and nothing in this plan treats it that way. The checker that
resolves the paths a record names is the clearest case: a record naming a path
with enough leading .. in it resolves to a file outside this repository, the
check passes, and the run reports that the record is in order because it read
something that has nothing to do with this tree.

Three properties, each of them a refusal with a fixture rather than a sentence in
a document.

The walk stays inside the repository. A symlink under experiments/ is refused
rather than followed. Refusing rather than resolving is the cheaper rule and the
one a reader can check, because a rule that follows a link and then judges where
it landed has to be right about every filesystem the release targets, and one of
them answers differently.

A path a record names resolves inside the repository or it is refused. This is
the same rule read from the other side and it is the one that bites in prose,
where the path is a string somebody typed rather than a link a tool produced. The
refusal names the record and the path, because a reader hitting this needs to
know which of the two is wrong.

The runner reads bounded amounts. A record above a stated size and a walk below a
stated depth, both with their numbers written where the check is defined and both
chosen so that no honest record comes near them. A checker that reads whatever it
is pointed at is a checker that stops on the first tree somebody builds badly, and
the first such tree here will be an accident rather than an attack.

Two things worth expecting rather than discovering.

A symlink is the fixture that will not survive the platform matrix. Whether a
symlink in a checkout arrives as a link or as a text file is a property of the
machine and of how the clone was made, so the case has to be built by the harness
at run time or asserted in a way that is true either way. Storing it as a tracked
link and hoping is how this test passes on one platform and silently tests nothing
on another, which is worse than not having it.

This is not a sandbox and the check should say so where it is defined. The runner
runs with the privileges of whoever started it and reads what it is pointed at.
What these refusals buy is that a record cannot make a green run out of a file
outside this repository, which is a claim about honesty rather than about
containment.

Done when the runner refuses a symlink under experiments/, refuses a path in a
record that resolves outside the repository, refuses a record above the stated
size, terminates on a fixture tree built to loop, each refusal has a fixture that
trips exactly it and no other, the bounds and the limit above are written where
the checks are defined, and the run passes on the current tree.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions