fix: pass HF token via git credential helper instead of embedding in remote URLs

#1
by GuillaumeSalouHF HF Staff - opened
Files changed (1) hide show
  1. worker.py +22 -7
worker.py CHANGED
@@ -215,11 +215,15 @@ def copy_repo_with_history(src: str, dst: str, repo_type: str) -> int:
215
  objects. The destination repo must already exist (pre-created by the
216
  calling Space).
217
 
218
- Auth: the canonical HF pattern (matches what `hf auth login
219
- --add-to-git-credential` writes) is HTTP Basic auth with username
220
- `hf_user` and the access token as the password. We embed those in the
221
- clone/push URLs. The token leaks into the temp `.git/config` only
222
- we delete the whole directory at the end.
 
 
 
 
223
  """
224
  if repo_type not in REPO_TYPE_URL_PREFIX:
225
  log(f"unsupported type: {repo_type}")
@@ -232,11 +236,22 @@ def copy_repo_with_history(src: str, dst: str, repo_type: str) -> int:
232
 
233
  prefix = REPO_TYPE_URL_PREFIX[repo_type]
234
  base = HF_ENDPOINT.replace("https://", "")
235
- src_url = f"https://hf_user:{token}@{base}/{prefix}{src}"
236
- dst_url = f"https://hf_user:{token}@{base}/{prefix}{dst}"
237
  src_label = f"{prefix}{src}"
238
  dst_label = f"{prefix}{dst}"
239
 
 
 
 
 
 
 
 
 
 
 
 
240
  _ensure_git_lfs()
241
  xet_available = _ensure_git_xet_binary()
242
 
 
215
  objects. The destination repo must already exist (pre-created by the
216
  calling Space).
217
 
218
+ Auth: the canonical HF pattern is HTTP Basic with username `hf_user` and
219
+ the access token as the password. Rather than embedding the token in the
220
+ clone/push URLs (which exposes it in the process command line, the temp
221
+ `.git/config`, and any git output echoed into the Job logs), we register a
222
+ git credential helper that reads the token from `HF_TOKEN` in the
223
+ environment at request time. The token therefore never appears on a command
224
+ line or in a config file; only the helper script (which references
225
+ `$HF_TOKEN`) is stored. The Job container is single-tenant and ephemeral,
226
+ so a global credential helper is safe here.
227
  """
228
  if repo_type not in REPO_TYPE_URL_PREFIX:
229
  log(f"unsupported type: {repo_type}")
 
236
 
237
  prefix = REPO_TYPE_URL_PREFIX[repo_type]
238
  base = HF_ENDPOINT.replace("https://", "")
239
+ src_url = f"https://{base}/{prefix}{src}"
240
+ dst_url = f"https://{base}/{prefix}{dst}"
241
  src_label = f"{prefix}{src}"
242
  dst_label = f"{prefix}{dst}"
243
 
244
+ # Authenticate via a credential helper that reads HF_TOKEN from the env at
245
+ # request time, so the token never lands in a remote URL, the process
246
+ # command line, or .git/config. Applies to ls-remote, fetch, lfs and push.
247
+ _run([
248
+ "git",
249
+ "config",
250
+ "--global",
251
+ "credential.helper",
252
+ '!f() { echo "username=hf_user"; echo "password=${HF_TOKEN}"; }; f',
253
+ ])
254
+
255
  _ensure_git_lfs()
256
  xet_available = _ensure_git_xet_binary()
257