Commit Graph
3 Commits
Author SHA1 Message Date
mhoennigandClaude a4c995592f Header-only control token, masked secrets, loopback default (v0.9.9)
Finishes the small items of the security audit in
docs/prs/2026-07-08-PR#000: TODO 3, 4 and 7.

The three mutating endpoints of BuildsApiController no longer accept the
control token as a `token` query parameter — only the X-GitTally-Token
header, which the bundled UI has always used. URLs end up in access logs,
proxy logs, browser history and Referer headers, and the token never
expires, so a historical log capture would yield a valid credential.

`config:print` masks git.token as `***` on both the raw and the --full
path and names the new --show-secrets flag in a leading YAML comment, so
the output stays parseable when piped. The setup script points at
--show-secrets where it used to steer the operator to the plain token.

`server.bindAddress` now defaults to 127.0.0.1: neither the UI nor the
API authenticates read access, so reaching GitTally should require the
host's reverse proxy. Existing .gittally.yml files keep their explicit
value; the managed nginx container needs `0.0.0.0` set deliberately,
which is noted in the release notes, docs/configuration.md and
docs/deployment.md.

Released as v0.9.9, which also carries the previous two commits.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-11 07:38:33 +02:00
mhoennigandClaude dea6770998 Harden secret-file creation, token comparison and git refname args
Works off the security audit in docs/prs/2026-07-08-PR#000: TODO 1, 8, 9
and 10, the four items that need no design decision.

New `SecretFiles` creates files holding secrets with mode 0600 and their
directories with 0700 *at creation*, as a file attribute, instead of
writing at the umask default and chmod-ing afterwards — that left a
window in which the Gitea token was world-readable, which matters on a
multi-tenant host. It is used by `init` for .git/gittally/.gittally.yml
and by `ControlTokenService` for the control token; the shell setup
script now writes its YAML in a `umask 077` subshell for the same reason.

`ControlTokenService.matches` hashes both sides with SHA-256 before
`MessageDigest.isEqual`, so the comparison always runs over two 32-byte
buffers and cannot return early on a length mismatch.

`GitService.checkout` and `fetchBranch` pass `--` before the refname, so
a branch named like an option cannot be read as one. `resetHardToOrigin`
keeps its plain form: `git reset --hard -- <commit>` is rejected outright
and its argument is already `origin/`-prefixed.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-11 07:09:34 +02:00
Michael Hoennig fdbbd0516a added setup-gittally-instance script: migrates legacy .gitTally configurations to YAML, sets up a GitTally instance on a Docker host, and prompts for Gitea secrets 2026-07-08 20:42:03 +02:00