shahar1 commented on code in PR #64105:
URL: https://github.com/apache/airflow/pull/64105#discussion_r4057226262


##########
providers/git/src/airflow/providers/git/hooks/git.py:
##########
@@ -293,22 +293,71 @@ def _github_app_askpass_env(self) -> Generator[None]:
                     self.env["GIT_TERMINAL_PROMPT"] = old_terminal_prompt
                     os.environ["GIT_TERMINAL_PROMPT"] = old_terminal_prompt
 
-    def _process_git_auth_url(self) -> None:
-        if not isinstance(self.repo_url, str):
+    def _extract_repo_host(self) -> str:
+        """Return the ``host[:port]`` of the repo url, as written."""
+        rest = str(self.repo_url).partition("://")[2]
+        return rest.partition("/")[0].rpartition("@")[2]
+
+    @contextlib.contextmanager
+    def _token_askpass_env(self):
+        """Hand the token to git through GIT_ASKPASS so it never reaches the 
repo URL."""
+        # Only http(s) consults GIT_ASKPASS, so writing the token to a temp 
script for an SSH
+        # connection that happens to carry one would put it on disk for 
nothing.
+        if not self.auth_token or not 
str(self.repo_url).startswith(("http://";, "https://";)):
+            yield
             return
-        if self.auth_token and self.repo_url.startswith("https://";):
-            encoded_user = urlquote(self.user_name, safe="")
-            encoded_token = urlquote(self.auth_token, safe="")
-            self.repo_url = self.repo_url.replace("https://";, 
f"https://{encoded_user}:{encoded_token}@";, 1)
-        elif self.auth_token and self.repo_url.startswith("http://";):
-            encoded_user = urlquote(self.user_name, safe="")
-            encoded_token = urlquote(self.auth_token, safe="")
-            self.repo_url = self.repo_url.replace("http://";, 
f"http://{encoded_user}:{encoded_token}@";, 1)
-        elif self.repo_url.startswith("http://";):
-            # if no auth token, use the repo url as is
-            pass
-        elif not self.repo_url.startswith("git@") and not 
self.repo_url.startswith("https://";):
-            self.repo_url = os.path.expanduser(self.repo_url)
+
+        host = self._extract_repo_host()
+        if not host:
+            yield
+            return
+
+        with tempfile.TemporaryDirectory() as askpass_dir:
+            askpass_path = os.path.join(askpass_dir, "askpass.sh")
+            # The credential reaches the script through the environment, so it 
is never written to
+            # disk. git names the target in $1 as 
``<scheme>://[user@]<host>[:port][/path]``, and
+            # matching it means a submodule hosted elsewhere gets nothing 
rather than this
+            # connection's token. Quoted expansions stay literal in a pattern, 
so an IPv6 host's
+            # brackets are not read as a glob character class.
+            with open(askpass_path, "w") as askpass_script:
+                askpass_script.write(
+                    """#!/bin/sh
+case "$1" in
+    
*"://$AIRFLOW_GIT_HOST'"*|*"://$AIRFLOW_GIT_HOST/"*|*"@$AIRFLOW_GIT_HOST'"*|*"@$AIRFLOW_GIT_HOST/"*)
 ;;

Review Comment:
   Could we replace this prompt-based guard with a URL-scoped credential 
helper, configured temporarily through GIT_CONFIG_COUNT / GIT_CONFIG_KEY_n / 
GIT_CONFIG_VALUE_n? Git would match the configured protocol and host, and the 
helper would receive structured credential fields instead of parsing a 
human-readable prompt. See [Git’s credential 
documentation](https://git-scm.com/docs/gitcredentials).
   On unpatched Git, a submodule URL such as https://github.com'@evil.com/x.git 
produces Password for 'https://github.com'@evil.com': . This matches the first 
pattern even though the destination is evil.com, so the script releases the 
token, which Git can then send there.
   Patched Git with prompt sanitization enabled blocks this example, but that 
prerequisite is undocumented and the current prompt-shape test does not 
exercise hostile usernames. Please add a regression test showing that this 
crafted URL receives no credentials while the intended host still authenticates.
   
   ---
   
   Drafted-by: Codex, reviewed by me



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to