Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Mask secret values in the log as it is written

e82bbe7ddc584dc54ee57c7ce3b97f933c9e9886 · Keenan Nemetz · 7d ago · parent 4ac42680

Mask secret values in the log as it is written

A step that prints a secret by accident used to put it in the attempt log, and
the log is streamed to the instance and kept. The runner now replaces every
value it was given with *** before the bytes reach the log file, so the copy
the server stores never holds one and a value split across two writes is still
caught: the mask holds back the last longest-1 bytes and the runner flushes at
the end of each step.

ci/redact is the one implementation, so a local `vole workflow run` masks its
terminal output the same way. Its own error text goes through the same mask,
because "the runtime message does not contain a value" should be true rather
than assumed.

It is best effort, and the docs say where it stops: a re-encoded value does not
match, a value shorter than four bytes is left alone because masking every
occurrence of it would rewrite the log, and an artifact or a site file is
published exactly as the step wrote it.

Slice 3 of #154.

docs/runner.md +8

@@ -152,6 +152,14 @@ repository does not have leaves its variable unset with one line in the log. The
152 152 value arrives over the SSH channel with the lease, is written `0600` in the job's
153 153 directory, and is removed with it.
154 154
155 Every delivered value is replaced with `***` in the log as the log is written, so
156 the file the server stores never holds one, and a value split across two writes is
157 still caught. The runner's own error text goes through the same mask. It is best
158 effort: a re-encoded value (base64, hex, a URL escape) no longer matches, and a
159 value shorter than 4 bytes is left alone because masking every occurrence of it
160 would rewrite the log. A step that writes a secret into an artifact publishes it —
161 the mask covers the log, not the files a job chooses to upload.
162
155 163 **A runner can read every secret a repository's jobs declare.** That is what running
156 164 the job means: the values arrive on the machine. The runner allowlist is the control
157 165 that decides whose machine it is, not the container. See