Skip to content

Fix input validation in PR details and issue creation endpoints#988

Open
nevyangelova wants to merge 4 commits intomasterfrom
MM-68027
Open

Fix input validation in PR details and issue creation endpoints#988
nevyangelova wants to merge 4 commits intomasterfrom
MM-68027

Conversation

@nevyangelova
Copy link
Copy Markdown
Contributor

@nevyangelova nevyangelova commented Mar 25, 2026

Summary

Add bounds checking to getRepoOwnerAndNameFromURL to prevent potential runtime panic from malformed input. Validate PR URLs in getPrsDetails handler before processing. Replace manual string splitting in createIssue with the existing parseRepo function which already performs proper validation.

QA Steps

PR details endpoint handles invalid input gracefully

  1. Open any channel and verify the GitHub sidebar loads your open PRs correctly
  2. Confirm PR review details display as expected

Issue creation handles invalid input gracefully

  1. Run /github issue create and create an issue on a valid repository
  2. Confirm the issue is created successfully on GitHub
  3. Verify the confirmation post appears in the channel

Ticket Link

https://mattermost.atlassian.net/browse/MM-68027

Change Impact: 🟡 Medium

Reasoning: The PR hardens input validation for GitHub repo/PR URL parsing and updates handlers to bail out or return errors on malformed inputs; changes are limited to API handlers and parsing helpers but modify handler behavior and a helper signature.

Regression Risk: Moderate — altering a shared helper's behavior and handler control flow can change responses for malformed inputs and could affect callers relying on previous permissive parsing; tests for the new helper were added but handler-level coverage remains limited.

** QA Recommendation:** Manual QA recommended: verify PR details load valid PRs and gracefully skip/log invalid PR URLs (no panics), and confirm /github issue create succeeds for valid repos and returns clear 400 errors for invalid repo strings. Skipping manual QA carries moderate risk.

Generated by CodeRabbitAI

@nevyangelova nevyangelova requested a review from a team as a code owner March 25, 2026 09:50
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fd747673-d17b-41f4-b12b-836317f92387

📥 Commits

Reviewing files that changed from the base of the PR and between 4ad4b85 and 23b6e3d.

📒 Files selected for processing (2)
  • server/plugin/api.go
  • server/plugin/api_test.go
✅ Files skipped from review due to trivial changes (1)
  • server/plugin/api_test.go

📝 Walkthrough

Walkthrough

getPrsDetails now filters out nil or unparsable PR entries; fetchPRDetails returns partial PRDetails and skips GitHub calls when URL parsing fails; getRepoOwnerAndNameFromURL now returns an error and uses URL-aware parsing; createIssue validates via parseRepo and returns 400 on invalid repo; tests added for URL parsing.

Changes

Cohort / File(s) Summary
API parsing & handlers
server/plugin/api.go
Changed getRepoOwnerAndNameFromURL signature to return (owner, repo, error) and replaced naive split with URL-aware parsing; getPrsDetails drops nil PRs and skips PRs whose URLs fail parsing; fetchPRDetails logs parse errors and returns partial PRDetails (no GitHub calls) for invalid URLs; createIssue uses parseRepo and returns 400 BadRequest on parse failure.
Unit tests
server/plugin/api_test.go
Extended TestParseRepo with empty-owner and empty-repo cases; added TestGetRepoOwnerAndNameFromURL covering GitHub REST API URLs, simple owner/repo strings, enterprise API URLs, and multiple malformed/empty-input error cases.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant Server as Server\n(plugin/api.go)
    participant GH as GitHub API
    Client->>Server: Request PR details (list of PRs)
    Server->>Server: validate PR list, drop nil entries
    alt PR URL parses
        Server->>GH: fetch PR reviews & reviewers
        GH-->>Server: return reviews & reviewers
        Server-->>Client: include full PRDetails
    else PR URL invalid
        Server->>Server: log warning, build partial PRDetails (URL, Number, empty slices)
        Server-->>Client: include partial PRDetails (no GH calls)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through URLs both near and far,
Parsed owner/repo from path and star,
If a link is broken, I pause and mend,
Keep partial truths and onward I send. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: hardening input validation for PR details and issue creation endpoints, which aligns with the primary objectives of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch MM-68027

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/plugin/api_test.go`:
- Around line 525-530: The test case "Valid full GitHub URL" asserts wrong
owner/repo values for the URL "https://api.github.com/repos/owner/repo/pulls/1";
update the test to expect expectedOwner="owner" and expectedRepo="repo" and
ensure the production function getRepoOwnerAndNameFromURL (used by
fetchPRDetails) is changed to parse the path segment pattern
"/repos/{owner}/{repo}/..." (i.e., find the "repos" segment and take the next
two segments as owner and repo) instead of returning the last two path segments;
adjust the test vector and confirm fetchPRDetails uses the corrected
getRepoOwnerAndNameFromURL behavior.

In `@server/plugin/api.go`:
- Around line 860-866: getRepoOwnerAndNameFromURL currently just returns the
last two path segments which breaks for full GitHub API URLs; update it to parse
the input as a URL (using net/url), split the path into segments, and if the
path contains a "repos" segment, take the two segments immediately after "repos"
as owner and repo; otherwise, if the path is just "owner/repo" (two segments),
return those; return an error if neither pattern matches. Ensure you update
references to getRepoOwnerAndNameFromURL accordingly and include clear error
messages when rejecting inputs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 506415de-16f9-46e3-9774-6c006d2438e4

📥 Commits

Reviewing files that changed from the base of the PR and between 09a11ca and 1889b15.

📒 Files selected for processing (2)
  • server/plugin/api.go
  • server/plugin/api_test.go

@nevyangelova
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 25, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nevyangelova nevyangelova added 2: Dev Review Requires review by a core committer 3: QA Review Requires review by a QA tester labels Mar 25, 2026
Copy link
Copy Markdown
Contributor

@avasconcelos114 avasconcelos114 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great improvement to the parsing of the repo owner and names! Only have one question about the API behavior, let me know what you think :)

for _, pr := range prList {
if _, _, err := getRepoOwnerAndNameFromURL(pr.URL); err != nil {
p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "invalid PR URL: " + pr.URL, StatusCode: http.StatusBadRequest})
return
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this early return causes the entire request to be treated as an error if a single item in the prList isn't valid

I'm wondering whether just excluding the invalid items from the response would be preferable from a UX perspective while still being able to address the cause of the issue

@nevyangelova
Copy link
Copy Markdown
Contributor Author

@avasconcelos114 thank you for the good suggestion, updated

Copy link
Copy Markdown
Contributor

@avasconcelos114 avasconcelos114 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/plugin/api.go`:
- Around line 769-775: The loop over prList dereferences pr.URL without checking
for nil, which can panic for payloads like [null]; update the loop that builds
validPRs to first check that pr != nil (and optionally log a warning with c.Log)
before calling getRepoOwnerAndNameFromURL(pr.URL), and continue on nil entries
so only non-nil PRs are validated and appended to validPRs.
- Around line 1770-1774: The parseRepo function currently only checks the split
length which allows strings like "owner/" or "/repo" to be treated as valid;
update parseRepo to validate that both returned parts (owner and repo) are
non-empty and return a descriptive error when either is empty so createIssue's
error path triggers correctly; locate and modify parseRepo to trim whitespace,
split by '/', ensure len(parts)==2 and parts[0] != "" and parts[1] != "", and
return an error message such as "invalid repository: missing owner or repo" when
the check fails.
- Around line 875-880: The parser currently returns segments[i+1] and
segments[i+2] immediately when it sees the "repos" segment; update that logic to
validate that both segments[i+1] (owner) and segments[i+2] (repo) are non-empty
before returning. In the loop that sets hasReposSegment and returns owner/repo,
add checks for empty strings (and return an appropriate error) so inputs like
"/repos//repo/..." or "/repos/owner//..." are rejected rather than propagated
downstream; keep the existing bounds check (i+2 < len(segments)) and only return
after both content checks pass.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: af6075d2-a79e-456d-9d55-17a1a53bdc44

📥 Commits

Reviewing files that changed from the base of the PR and between 7e8757f and 4ad4b85.

📒 Files selected for processing (1)
  • server/plugin/api.go

@nevyangelova nevyangelova removed the 2: Dev Review Requires review by a core committer label Mar 26, 2026
@edgarbellot edgarbellot self-requested a review March 26, 2026 17:01
@edgarbellot edgarbellot added the 3: Security Review Review requested from Security Team label Mar 26, 2026
Copy link
Copy Markdown

@ogi-m ogi-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@ogi-m ogi-m removed the 3: QA Review Requires review by a QA tester label Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3: Security Review Review requested from Security Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants