mirror of
https://gitea.com/gitea/runner.git
synced 2026-08-26 13:57:46 +00:00
fix: mask secrets on every path they leave a job (#1188)
A secret in a matrix value reached the log in the clear:
```yaml
strategy:
matrix:
include: "${{ github.token }}"
```
Chasing that one route is pointless, so this masks every sink a secret leaves a job by: the uploaded log rows and the on-disk `job.log`, both through one choke point in `appendLogRow`; the runner's own log, which is where planning errors like that one land with no job logger in reach; the job logger's stdout under debug logging; job summaries; job outputs; and the job name that becomes a container name.
Values the runner knows but the job never declared, the proxy password and the task token, are hidden the same way. Masks apply longest first, since `strings.Replacer` matches in argument order and one secret prefixing another would otherwise mask the prefix and print the rest.
### What changes for users
An output whose value carries a secret is skipped with a warning instead of sent, matching GitHub. Output that showed a secret now shows `***`. `ACTIONS_STEP_DEBUG` and `ACTIONS_RUNNER_DEBUG` are never masked, also matching GitHub, so an output of `true` still reaches the jobs that need it.
Each fix has a test that fails without it.
Reviewed-on: https://gitea.com/gitea/runner/pulls/1188
Reviewed-by: bircni <bircni@icloud.com>
Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
@@ -24,6 +24,7 @@ import (
|
||||
"gitea.com/gitea/runner/internal/pkg/labels"
|
||||
"gitea.com/gitea/runner/internal/pkg/lock"
|
||||
"gitea.com/gitea/runner/internal/pkg/metrics"
|
||||
"gitea.com/gitea/runner/internal/pkg/report"
|
||||
"gitea.com/gitea/runner/internal/pkg/ver"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
@@ -283,7 +284,7 @@ func initLogging(cfg *config.Config) {
|
||||
FullTimestamp: true,
|
||||
CallerPrettyfier: callPrettyfier,
|
||||
}
|
||||
log.SetFormatter(format)
|
||||
log.SetFormatter(report.MaskingFormatter(format))
|
||||
|
||||
l := cfg.Log.Level
|
||||
if l == "" {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"gitea.com/gitea/runner/internal/pkg/config"
|
||||
"gitea.com/gitea/runner/internal/pkg/report"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -57,10 +58,15 @@ func TestInitLoggingSetsLevelAndCaller(t *testing.T) {
|
||||
log.SetReportCaller(oldReportCaller)
|
||||
})
|
||||
|
||||
oldFormatter := log.StandardLogger().Formatter
|
||||
t.Cleanup(func() { log.SetFormatter(oldFormatter) })
|
||||
|
||||
cfg := &config.Config{}
|
||||
cfg.Log.Level = "debug"
|
||||
initLogging(cfg)
|
||||
|
||||
require.Equal(t, log.DebugLevel, log.GetLevel())
|
||||
require.True(t, log.StandardLogger().ReportCaller)
|
||||
// act plans a job on this logger, so a live task's secrets have to be masked out of it
|
||||
require.IsType(t, report.MaskingFormatter(nil), log.StandardLogger().Formatter)
|
||||
}
|
||||
|
||||
@@ -519,6 +519,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
||||
Env: envs,
|
||||
ProxyEnv: proxyEnv,
|
||||
Secrets: task.Secrets,
|
||||
ExtraMasks: append(proxyPasswords(), preset.Token),
|
||||
GitHubInstance: strings.TrimSuffix(r.client.Address(), "/"),
|
||||
NoSkipCheckout: true,
|
||||
DisableActEnv: r.cfg.Runner.SetActEnv != nil && !*r.cfg.Runner.SetActEnv,
|
||||
|
||||
Reference in New Issue
Block a user