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>
This commit is contained in:
@@ -9,6 +9,7 @@ import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.attribute.PosixFilePermissions
|
||||
|
||||
class InitCommandTest : FunSpec() {
|
||||
private val gitService = mockk<GitService>()
|
||||
@@ -37,6 +38,20 @@ class InitCommandTest : FunSpec() {
|
||||
repoContent shouldContain "account: \"\"" // no user in https URL
|
||||
}
|
||||
|
||||
test("creates the secrets config and its directory readable only by the owner") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
|
||||
every { gitService.getTopLevel(tempDir) } returns tempDir
|
||||
every { gitService.getOriginUrl(tempDir) } returns "https://git.example.org/my-org/my-repo.git"
|
||||
|
||||
initCommand.run()
|
||||
|
||||
val repoConfig = tempDir.resolve(".git/gittally/.gittally.yml")
|
||||
PosixFilePermissions.toString(Files.getPosixFilePermissions(repoConfig)) shouldBe "rw-------"
|
||||
PosixFilePermissions.toString(Files.getPosixFilePermissions(repoConfig.parent)) shouldBe "rwx------"
|
||||
}
|
||||
|
||||
test("detects account from https url") {
|
||||
val tempDir = Files.createTempDirectory("gittally-init-test")
|
||||
initCommand.workingDir = tempDir
|
||||
|
||||
Reference in New Issue
Block a user