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/reference/workflow-reference.md +11−2

@@ -589,6 +589,17 @@ mounted at `/run/vole`, and the runner sources it before each step. There is no
589 589 expressions layer: a value is a variable, and a step that builds a name at runtime
590 590 reads the file itself.
591 591
592 The runner replaces each delivered value with `***` as the log is written, so a step
593 that prints one by accident does not put it in the log the instance stores. This is
594 best effort, and worth knowing exactly:
595
596 - a value that has been re-encoded — base64, hex, a URL escape, one field of a
597 connection string — no longer matches, and is not masked;
598 - a value shorter than 4 bytes is not masked at all, because replacing every
599 occurrence of `1` or `yes` would rewrite the log and protect nothing;
600 - an artifact, a site file or a release attachment is stored as the step wrote it,
601 so a secret a step writes to a file it publishes is published.
602
592 603 ### `steps`
593 604
594 605 A non-empty list of shell steps, at most 100. Steps run in order. A step that exits
@@ -685,8 +696,6 @@ It does not support:
685 696 - a build matrix or per-step conditions (`strategy`, `if`, `continue-on-error`)
686 697 - step-scoped secrets, expressions for building a secret name, or a value written
687 698 in the workflow file; secrets are job-scoped and the instance holds the values
688 - masking of a value in a step's output: a step that prints a secret writes it to
689 the log, so a workflow is responsible for what its steps print
690 699 - expressions or contexts (`${{ }}`); nothing outside the shell is interpolated
691 700 - service containers, cache keys, or artifact downloads between jobs
692 701 - job-level timeouts, concurrency groups, or cancel-in-progress