Expand description
Confine the files that a run writes on request (baselines, snapshots and report files) to the project.
A path must resolve inside the project root, or inside the Git work tree
that contains the root when the working directory is inside that tree too,
or inside a shared directory: the CI workspace (GITHUB_WORKSPACE, GitLab
CI_PROJECT_DIR) and the temp directories (RUNNER_TEMP, the system temp
directory), each when it is set. An existing character device or named
pipe (/dev/null, /dev/stdout, process substitution) is also allowed,
because a write to it cannot put a file anywhere. On Windows the null
device (NUL) is allowed for the same reason.
The command line layer checks each path before the analysis starts and
then records the scope with confine. The writers call create_file
or write_file, which resolve and check the path again right before the
write and do not follow a symlink at the final component.
This narrows the window for a path that another local user swaps for a symlink, from the whole analysis to the moment of the write. It does not close the window for an intermediate directory: a directory swapped between the last parent check and the open call is still followed. On Windows the final component is checked just before the open, so a small window stays there too.
Symlinks are resolved on both sides: on the part of the path that exists,
and on each allowed directory. So a link inside the root that points
outside it does not open a way out, and /var and /private/var on macOS
compare equal.
Structs§
- Write
Scope - The directories a run may write into.
Enums§
- Write
Failure - Why a confined write did not happen.
- Write
Target - What kind of file a write targets. The kind selects the scope that the write is checked against.
Functions§
- confine
- Record the scopes that later writes are checked against. The first call wins. Without a call, writes are not confined, but they still do not follow a symlink at the final component that appears after the path was resolved.
- create_
file - Create or truncate
pathfor writing, after the checks this module describes. Missing parent directories are created. - resolve
- Resolve
paththe way a write would reach it: symlinks and..in the part that exists are resolved by the file system, and the rest, which a write would create, is normalised lexically. A dangling symlink is followed to its target, because a write through it lands there. - shared_
dirs - The shared directories a run may write into: each directory in
GITHUB_WORKSPACE,CI_PROJECT_DIRandRUNNER_TEMPthat is set and not empty, and the system temp directory. The CI workspace keeps a job working that checks the repository out into a subdirectory and writes its report beside it. A directory that does not exist is skipped, because it cannot be resolved. - write_
file - Write
contentstopaththroughcreate_file.