security: harden granthi-link + client against 7 codex findings

1. CRITICAL account-takeover by login collision: persist zitadel_sub ->
   gitea_login identity map (state.json, 0600, atomic); mapping wins,
   deleted logins re-created only if service-created, existing unmapped
   logins bind only on verified email match, else 409; token never
   minted before binding passes
2. test_mode now gated behind GRANTHI_LINK_ALLOW_TEST_MODE=1 env
3. refuse startup unless config.json is 0600/0400 and owned by service
4. client config created O_CREAT 0600 (no write-then-chmod window)
5. credential-helper command paths shlex-quoted
6. POST bodies capped at 64KB (413); missing/invalid Content-Length rejected
7. Gitea 409 on user create handled idempotently (re-fetch + verify email)

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Nirav Patel
2026-08-19 09:17:26 -04:00
co-authored by Claude Fable 5
parent 1c8fcb23d8
commit c674db4746
8 changed files with 610 additions and 55 deletions
+16 -4
View File
@@ -29,6 +29,7 @@ import base64
import json
import os
import re
import shlex
import signal
import subprocess
import sys
@@ -101,9 +102,12 @@ def load_config():
def save_config(cfg):
os.makedirs(CONFIG_DIR, mode=0o700, exist_ok=True)
tmp = CONFIG_PATH + ".tmp"
with open(tmp, "w") as f:
# O_CREAT with mode 0600 -- the file is never observable with wider
# permissions (a write-then-chmod sequence leaves a umask-sized window
# in which the token is world-readable).
fd = os.open(tmp, os.O_CREAT | os.O_WRONLY | os.O_TRUNC, 0o600)
with os.fdopen(fd, "w") as f:
json.dump(cfg, f, indent=2)
os.chmod(tmp, 0o600)
os.replace(tmp, CONFIG_PATH)
@@ -220,9 +224,17 @@ def cmd_git_credential(argv):
return 0
def credential_helper_value():
"""Shell command git runs for credentials. Both paths are shlex-quoted:
a Python or script path containing spaces (or shell metacharacters)
must neither break the helper nor inject into the shell."""
return "!{} {} git-credential".format(
shlex.quote(sys.executable),
shlex.quote(os.path.abspath(__file__)))
def install_credential_helper(folder):
helper = f"!{sys.executable} {os.path.abspath(__file__)} git-credential"
git(folder, "config", "credential.helper", helper)
git(folder, "config", "credential.helper", credential_helper_value())
# --------------------------------------------------------------------------