Skip to content

add debug logs for github api requests #2047

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 24, 2025

Conversation

motatoes
Copy link
Contributor

No description provided.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Summary

This PR adds comprehensive debug logging for GitHub API requests by implementing a custom HTTP round tripper (loggingRoundTripper) that intercepts and logs all HTTP traffic between the Digger backend and GitHub's API. The implementation wraps the existing GitHub client transport in the Get method of DiggerGithubRealClientProvider, capturing detailed information about requests (method, URL, headers) and responses (status, headers, full body content).

The change integrates seamlessly with the existing GitHub client creation workflow in backend/utils/github.go. When a GitHub client is created through the Get method, it now automatically includes the logging wrapper around the installation transport. This ensures all GitHub API calls made through the client - including those from the underlying go-github library - are consistently logged at debug level.

This enhancement aligns with the codebase's focus on observability and debugging, particularly important given the complex GitHub App installation management, webhook processing, and API interactions that Digger handles. The logging uses structured logging via slog which is consistent with the existing logging patterns throughout the codebase.

Confidence score: 2/5

  • This PR has significant security and performance risks that make it unsafe for production environments
  • The implementation logs sensitive authentication headers and full response bodies which could expose tokens and private data
  • The backend/utils/github.go file needs careful security review before merging

PR Description Notes:

  • The PR description is empty (null) - consider adding details about the purpose and scope of the logging changes

1 file reviewed, 1 comment

Edit Code Review Bot Settings | Greptile

slog.Debug("GitHub API Request",
"method", req.Method,
"url", req.URL.String(),
"headers", req.Header,
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Logging headers may expose sensitive authentication tokens in debug logs. Consider filtering or redacting authorization headers.

Copy link
Contributor

bismuthdev bot commented Jul 23, 2025

Cancelled.

Copy link
Contributor

bismuthdev bot commented Jul 24, 2025

Security Bugs Summary in GitHub API Logging

Total bugs found: 5

Critical Security Issues

  1. Sensitive Response Data Exposure - The logger was recording complete API response bodies at debug level, potentially exposing access tokens, credentials, and personal data in log files.

  2. Unfiltered Request Headers - All request headers were being logged without filtering, exposing authentication tokens, API keys, session cookies, and other credentials.

  3. Unfiltered Response Headers - Similar to request headers, response headers containing sensitive information were logged without redaction.

  4. Unbounded Memory Usage - The code read entire response bodies into memory regardless of size, creating potential memory issues and security risks for large responses.

  5. Consumed Response Body - When errors occurred while reading the response body, the original (now empty) response was returned to callers, causing downstream failures.

These issues primarily revolve around improper handling of sensitive data in logs and memory management problems when processing API responses.

Comment on lines 36 to 40
slog.Debug("GitHub API Response",
"status", resp.Status,
"headers", resp.Header,
"body", string(bodyBytes),
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The LoggingRoundTripper is logging the entire response body from GitHub API calls at debug level. This is a security risk because:

  1. API responses may contain sensitive information like access tokens, credentials, or personal data
  2. When debug logs are enabled in production, this sensitive information would be exposed in log files
  3. Log files are often accessible to more people than should have access to these credentials
  4. Log files might be sent to third-party logging services without proper redaction

The fix replaces the full body logging with just logging the length of the response body, which provides debugging value (confirming response size) without exposing sensitive content.

Suggested change
slog.Debug("GitHub API Response",
"status", resp.Status,
"headers", resp.Header,
"body", string(bodyBytes),
)
slog.Debug("GitHub API Response",
"status", resp.Status,
"headers", resp.Header,
"bodyLength", len(bodyBytes),
)

Comment on lines 28 to 33
// Read and clone response body for logging
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
slog.Error("Failed to read response body", "error", err)
return resp, err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

In the RoundTrip method of LoggingRoundTripper, when there's an error reading the response body (lines 29-32), the function returns the original response object, but the response body has already been consumed by the io.ReadAll call. This means the caller would receive a response with an empty/consumed body, which would likely cause issues for any code trying to read the response body later.

The fix restores the response body with an empty buffer when there's an error reading it, which is better than returning a consumed body. This way, the caller will at least get an empty body rather than an error when trying to read from a closed reader.

Suggested change
// Read and clone response body for logging
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
slog.Error("Failed to read response body", "error", err)
return resp, err
}
// Read and clone response body for logging
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
slog.Error("Failed to read response body", "error", err)
// When we can't read the body, we should still restore it to prevent returning a consumed body
resp.Body = io.NopCloser(bytes.NewBuffer([]byte{}))
return resp, err
}

Comment on lines 28 to 40
// Read and clone response body for logging
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
slog.Error("Failed to read response body", "error", err)
return resp, err
}
resp.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) // restore the body for the actual client

slog.Debug("GitHub API Response",
"status", resp.Status,
"headers", resp.Header,
"body", string(bodyBytes),
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The current implementation in trip_logger.go reads the entire response body into memory for every GitHub API request using io.ReadAll(resp.Body). This is problematic for large responses as it:

  1. Consumes memory proportional to the response size with no upper bound
  2. Could lead to out-of-memory errors for very large responses
  3. Logs the entire response body regardless of size, which is inefficient and potentially risky for large payloads

The fix implements a size-limited approach that:

  1. Uses a TeeReader to simultaneously read the body while writing to a buffer
  2. Limits the amount read for logging purposes to 1MB
  3. Properly drains and closes the original response body
  4. Restores the body for the client using the buffer
  5. Adds metadata about response size and truncation to the logs

This approach maintains the logging functionality while preventing unbounded memory usage.

Comment on lines 16 to 20
slog.Debug("GitHub API Request",
"method", req.Method,
"url", req.URL.String(),
"headers", req.Header,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The code in trip_logger.go logs all request headers without filtering sensitive information. This is a security vulnerability as it could expose authentication tokens, API keys, and other sensitive data in the logs.

The current implementation logs the entire req.Header object, which may contain:

  • Authorization tokens
  • API keys
  • Session cookies
  • Other sensitive credentials

This information could be exposed in log files and potentially accessed by unauthorized parties. The fix creates a sanitized copy of the headers and redacts values for common sensitive header names before logging.

Suggested change
slog.Debug("GitHub API Request",
"method", req.Method,
"url", req.URL.String(),
"headers", req.Header,
)
// Create a copy of headers to sanitize sensitive information
sanitizedHeaders := make(net.Header)
for k, v := range req.Header {
// Skip sensitive headers or redact their values
if k == "Authorization" || k == "Cookie" || k == "X-GitHub-Token" ||
strings.Contains(strings.ToLower(k), "key") ||
strings.Contains(strings.ToLower(k), "secret") ||
strings.Contains(strings.ToLower(k), "token") ||
strings.Contains(strings.ToLower(k), "password") {
sanitizedHeaders[k] = []string{"[REDACTED]"}
} else {
sanitizedHeaders[k] = v
}
}
slog.Debug("GitHub API Request",
"method", req.Method,
"url", req.URL.String(),
"headers", sanitizedHeaders,
)

Comment on lines 36 to 40
slog.Debug("GitHub API Response",
"status", resp.Status,
"headers", resp.Header,
"body", string(bodyBytes),
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The code in trip_logger.go logs all response headers and the complete response body without filtering sensitive information. This is a security vulnerability as it could expose authentication tokens, API keys, and other sensitive data in the logs.

The current implementation logs:

  1. The entire resp.Header object, which may contain sensitive tokens or cookies
  2. The complete response body, which might include sensitive data or tokens

This information could be exposed in log files and potentially accessed by unauthorized parties. The fix:

  1. Creates a sanitized copy of the headers and redacts values for common sensitive header names
  2. Limits the logging of large response bodies to prevent excessive log sizes and reduce the chance of exposing sensitive data

Additionally, the fix adds a string import that was missing in the original code.

Suggested change
slog.Debug("GitHub API Response",
"status", resp.Status,
"headers", resp.Header,
"body", string(bodyBytes),
)
// Create a copy of headers to sanitize sensitive information
sanitizedHeaders := make(net.Header)
for k, v := range resp.Header {
// Skip sensitive headers or redact their values
if k == "Authorization" || k == "Cookie" || k == "X-GitHub-Token" ||
strings.Contains(strings.ToLower(k), "key") ||
strings.Contains(strings.ToLower(k), "secret") ||
strings.Contains(strings.ToLower(k), "token") ||
strings.Contains(strings.ToLower(k), "password") {
sanitizedHeaders[k] = []string{"[REDACTED]"}
} else {
sanitizedHeaders[k] = v
}
}
// Also consider sanitizing the response body if it might contain sensitive data
// For simplicity, we're just logging the length for large responses
bodyToLog := string(bodyBytes)
if len(bodyBytes) > 1000 {
bodyToLog = fmt.Sprintf("[%d bytes]", len(bodyBytes))
}
slog.Debug("GitHub API Response",
"status", resp.Status,
"headers", sanitizedHeaders,
"body", bodyToLog,
)

Copy link
Contributor

bismuthdev bot commented Jul 24, 2025

Bug Summary Report

Total Bugs Found: 2

Bug Summaries:

  1. Security Vulnerability in Request Logging (Critical)

    • The LoggingRoundTripper in backend/utils/trip_logger.go logs the full URL of requests including query parameters
    • This could expose sensitive information like tokens, API keys, and credentials in logs
    • Affects lines 14-17
  2. Excessive Debug Logging (Moderate)

    • All GitHub API requests and responses are logged at DEBUG level regardless of need
    • This can cause log flooding in high-traffic environments
    • The GitHub client is wrapped with LoggingRoundTripper in multiple locations, amplifying the issue
    • Affects lines 13-32

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Summary

This PR refactors the GitHub API logging implementation by addressing the security concerns raised in the previous review. The changes move the LoggingRoundTripper from inline code to a separate utility file (backend/utils/trip_logger.go) and significantly improve security by removing the logging of sensitive headers and response bodies.

The refactored implementation now only logs essential request information (method and URL) and specific GitHub rate limit headers (X-RateLimit-Remaining, X-RateLimit-Used, etc.), which are crucial for monitoring API quota usage without exposing authentication tokens or sensitive data. The logging functionality is consistently applied across both the community edition (backend/utils/github.go) and enterprise edition (ee/backend/providers/github/providers.go) GitHub client providers.

The change maintains the same integration point in the Get method where the logging wrapper is applied to the GitHub installation transport, ensuring comprehensive coverage of all GitHub API interactions while following secure logging practices.

Confidence score: 4/5

  • This PR successfully addresses the major security concerns from the previous implementation by removing sensitive data logging
  • The refactored approach focuses on operationally useful information (rate limits) while maintaining security
  • The enterprise edition implementation has some dead code that should be cleaned up, but it doesn't affect functionality

3 files reviewed, 2 comments

Edit Code Review Bot Settings | Greptile

Comment on lines 14 to 17
slog.Debug("GitHub API Request",
"method", req.Method,
"url", req.URL.String(),
)
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Logging the full URL may expose sensitive query parameters or tokens. Consider sanitizing URLs before logging.

Comment on lines +83 to +85
clientWithLogging := &net.Client{
Transport: &utils.LoggingRoundTripper{Rt: itr},
}
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Consider adding contextual identifiers like githubAppId and installationId to the logging transport to maintain consistency with backend implementation and improve traceability

Comment on lines 14 to 17
slog.Debug("GitHub API Request",
"method", req.Method,
"url", req.URL.String(),
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The LoggingRoundTripper logs the full URL of requests including query parameters using req.URL.String(). This is a security vulnerability as it could leak sensitive information like tokens, API keys, or credentials that might be present in query parameters to logs.

The fix creates a copy of the URL, identifies potentially sensitive query parameters by looking for common keywords in parameter names (token, key, secret, password, auth, credential), and redacts their values before logging. This ensures that sensitive information is not exposed in logs while still providing useful debugging information about the request.

Suggested change
slog.Debug("GitHub API Request",
"method", req.Method,
"url", req.URL.String(),
)
// Create a copy of the URL to sanitize sensitive information
sanitizedURL := *req.URL
q := sanitizedURL.Query()
// Redact potentially sensitive query parameters
for key := range q {
if strings.Contains(strings.ToLower(key), "token") ||
strings.Contains(strings.ToLower(key), "key") ||
strings.Contains(strings.ToLower(key), "secret") ||
strings.Contains(strings.ToLower(key), "password") ||
strings.Contains(strings.ToLower(key), "auth") ||
strings.Contains(strings.ToLower(key), "credential") {
q.Set(key, "[REDACTED]")
}
}
sanitizedURL.RawQuery = q.Encode()
slog.Debug("GitHub API Request",
"method", req.Method,
"url", sanitizedURL.String(),
)

Comment on lines 13 to 32
// Log the request
slog.Debug("GitHub API Request",
"method", req.Method,
"url", req.URL.String(),
)

resp, err := lrt.Rt.RoundTrip(req)
if err != nil {
slog.Error("GitHub API Request failed", "error", err)
return nil, err
}

slog.Debug("GitHub API Response",
"status", resp.Status,
"X-RateLimit-Limit", resp.Header.Get("X-RateLimit-Limit"),
"X-RateLimit-Remaining", resp.Header.Get("X-RateLimit-Remaining"),
"X-RateLimit-Used", resp.Header.Get("X-RateLimit-Used"),
"X-RateLimit-Resource", resp.Header.Get("X-RateLimit-Resource"),
"X-RateLimit-Reset", resp.Header.Get("X-RateLimit-Reset"),
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The current implementation logs every GitHub API request and response at DEBUG level, which could generate excessive log data in environments with many GitHub API requests. This is particularly problematic because:

  1. The GitHub client is wrapped with the LoggingRoundTripper in both backend/utils/github.go and ee/backend/providers/github/providers.go, meaning all GitHub API calls are logged.
  2. Each API call generates two debug log entries (request and response) with multiple fields.
  3. In high-traffic environments or during operations that make many API calls (like scanning repositories or processing webhooks), this can lead to log flooding.

The fix adds a conditional check based on an environment variable DEBUG_GITHUB_API, which allows operators to explicitly enable this verbose logging only when needed for troubleshooting, while keeping logs manageable in normal operation.

Suggested change
// Log the request
slog.Debug("GitHub API Request",
"method", req.Method,
"url", req.URL.String(),
)
resp, err := lrt.Rt.RoundTrip(req)
if err != nil {
slog.Error("GitHub API Request failed", "error", err)
return nil, err
}
slog.Debug("GitHub API Response",
"status", resp.Status,
"X-RateLimit-Limit", resp.Header.Get("X-RateLimit-Limit"),
"X-RateLimit-Remaining", resp.Header.Get("X-RateLimit-Remaining"),
"X-RateLimit-Used", resp.Header.Get("X-RateLimit-Used"),
"X-RateLimit-Resource", resp.Header.Get("X-RateLimit-Resource"),
"X-RateLimit-Reset", resp.Header.Get("X-RateLimit-Reset"),
)
// Only log GitHub API requests at DEBUG level if DEBUG_GITHUB_API is set
if os.Getenv("DEBUG_GITHUB_API") == "true" {
slog.Debug("GitHub API Request",
"method", req.Method,
"url", req.URL.String(),
)
}
resp, err := lrt.Rt.RoundTrip(req)
if err != nil {
slog.Error("GitHub API Request failed", "error", err)
return nil, err
}
// Only log GitHub API responses at DEBUG level if DEBUG_GITHUB_API is set
if os.Getenv("DEBUG_GITHUB_API") == "true" {
slog.Debug("GitHub API Response",
"status", resp.Status,
"X-RateLimit-Limit", resp.Header.Get("X-RateLimit-Limit"),
"X-RateLimit-Remaining", resp.Header.Get("X-RateLimit-Remaining"),
"X-RateLimit-Used", resp.Header.Get("X-RateLimit-Used"),
"X-RateLimit-Resource", resp.Header.Get("X-RateLimit-Resource"),
"X-RateLimit-Reset", resp.Header.Get("X-RateLimit-Reset"),
)
}

Copy link
Contributor

bismuthdev bot commented Jul 24, 2025

Bug Summary Report

Overview

A total of 3 bugs were found in the codebase, all located in the backend/utils/trip_logger.go file. These bugs affect the GitHub API request logging functionality.

Summary of Bugs

  1. Potential Nil Pointer Dereference - The LoggingRoundTripper.RoundTrip method doesn't check if resp.Header is nil before accessing it, which could cause a panic in edge cases with unusual API responses.

  2. Security Concern: Sensitive Information Logging - Raw URL paths of GitHub API requests are being logged without sanitization, potentially exposing sensitive information like repository names, PR numbers, and other identifiers in debug logs.

  3. Inadequate Rate Limit Handling - The logger doesn't specifically detect or handle GitHub API rate limit exceeded errors. These critical events are only logged at debug level, making them less visible and potentially causing silent failures in production.

The most critical bug is the rate limit handling issue, as it could lead to silent failures in production environments when API limits are reached, followed by the security concern of logging sensitive information.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Greptile Summary

This PR makes a final security refinement to the GitHub API logging implementation by changing the logged URL information from the full URL string (req.URL.String()) to only the URL path (req.URL.Path) in the LoggingRoundTripper. This change prevents sensitive query parameters, authentication tokens, or other credentials that might be present in URL query strings from being exposed in debug logs.

The modification occurs in backend/utils/trip_logger.go at line 16, where the logging statement now captures only the API endpoint path (e.g., /repos/owner/repo/pulls) rather than the complete URL with potential sensitive parameters. This maintains the debugging utility of knowing which GitHub API endpoints are being called while eliminating the security risk of accidentally logging authentication data embedded in URLs.

This change complements the previous security improvements made in earlier iterations of this PR, where sensitive headers and response bodies were already removed from logging. The LoggingRoundTripper continues to be used in the GitHub client creation process and will now provide secure, operationally useful logging for all GitHub API interactions across both community and enterprise editions.

Confidence score: 5/5

  • This is a focused security improvement that eliminates the risk of logging sensitive URL parameters without affecting functionality
  • The change maintains all debugging benefits while removing potential credential exposure
  • No files need additional attention as this is a straightforward, single-line security fix

1 file reviewed, no comments

Edit Code Review Bot Settings | Greptile

Comment on lines +14 to +17
slog.Debug("GitHub API Request",
"method", req.Method,
"url_path", req.URL.Path,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The LoggingRoundTripper logs the raw URL path of GitHub API requests, which could contain sensitive information like repository names, PR numbers, or other identifiers. This information is logged at the debug level, but it's still a potential security concern as these logs might be collected and viewed by various people.

The URL path should be sanitized before logging to remove or mask sensitive information. This would require adding a sanitization function to process the URL path before logging it.

Additionally, a sanitization function should be added to the file:

// sanitizeUrlPath removes or masks sensitive information from GitHub API URL paths
func sanitizeUrlPath(path string) string {
	// Implementation could use regex to replace repository names, PR numbers, etc.
	// with placeholders or masked values
	// For example: "/repos/username/repo-name/pulls/123" -> "/repos/[REDACTED]/[REDACTED]/pulls/[ID]"
	
	// Simple implementation for demonstration
	// A more robust implementation would use proper regex patterns
	return path
}

This change helps protect sensitive information while still providing useful debugging information about API requests.

Suggested change
slog.Debug("GitHub API Request",
"method", req.Method,
"url_path", req.URL.Path,
)
// Sanitize URL path to remove potentially sensitive information
sanitizedPath := sanitizeUrlPath(req.URL.Path)
slog.Debug("GitHub API Request",
"method", req.Method,
"url_path", sanitizedPath,
)

Comment on lines 19 to 32
resp, err := lrt.Rt.RoundTrip(req)
if err != nil {
slog.Error("GitHub API Request failed", "error", err)
return nil, err
}

slog.Debug("GitHub API Response",
"status", resp.Status,
"X-RateLimit-Limit", resp.Header.Get("X-RateLimit-Limit"),
"X-RateLimit-Remaining", resp.Header.Get("X-RateLimit-Remaining"),
"X-RateLimit-Used", resp.Header.Get("X-RateLimit-Used"),
"X-RateLimit-Resource", resp.Header.Get("X-RateLimit-Resource"),
"X-RateLimit-Reset", resp.Header.Get("X-RateLimit-Reset"),
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The LoggingRoundTripper currently logs GitHub API rate limit information at the debug level, but it doesn't specifically detect or handle rate limit exceeded errors. When GitHub API rate limits are exceeded, the API returns a 403 status code with a "X-RateLimit-Remaining" header value of "0".

This bug fix adds specific detection and error-level logging for rate limit exceeded conditions, which will make these critical events more visible in logs. This is important because rate limit exceeded errors can cause API requests to fail silently if they're only logged at debug level, potentially leading to hard-to-diagnose issues in production.

The fix maintains the existing debug logging for normal responses while adding special handling for the rate limit exceeded case.

Suggested change
resp, err := lrt.Rt.RoundTrip(req)
if err != nil {
slog.Error("GitHub API Request failed", "error", err)
return nil, err
}
slog.Debug("GitHub API Response",
"status", resp.Status,
"X-RateLimit-Limit", resp.Header.Get("X-RateLimit-Limit"),
"X-RateLimit-Remaining", resp.Header.Get("X-RateLimit-Remaining"),
"X-RateLimit-Used", resp.Header.Get("X-RateLimit-Used"),
"X-RateLimit-Resource", resp.Header.Get("X-RateLimit-Resource"),
"X-RateLimit-Reset", resp.Header.Get("X-RateLimit-Reset"),
)
resp, err := lrt.Rt.RoundTrip(req)
if err != nil {
slog.Error("GitHub API Request failed", "error", err)
return nil, err
}
// Check for rate limit exceeded (status code 403 with specific message)
if resp.StatusCode == 403 && resp.Header.Get("X-RateLimit-Remaining") == "0" {
slog.Error("GitHub API Rate Limit Exceeded",
"status", resp.Status,
"X-RateLimit-Limit", resp.Header.Get("X-RateLimit-Limit"),
"X-RateLimit-Reset", resp.Header.Get("X-RateLimit-Reset"),
"X-RateLimit-Resource", resp.Header.Get("X-RateLimit-Resource"),
)
} else {
slog.Debug("GitHub API Response",
"status", resp.Status,
"X-RateLimit-Limit", resp.Header.Get("X-RateLimit-Limit"),
"X-RateLimit-Remaining", resp.Header.Get("X-RateLimit-Remaining"),
"X-RateLimit-Used", resp.Header.Get("X-RateLimit-Used"),
"X-RateLimit-Resource", resp.Header.Get("X-RateLimit-Resource"),
"X-RateLimit-Reset", resp.Header.Get("X-RateLimit-Reset"),
)
}

Co-authored-by: bismuthdev[bot] <177057995+bismuthdev[bot]@users.noreply.github.com>
Copy link
Contributor

bismuthdev bot commented Jul 24, 2025

Bug Summary Report

Total Bugs Found: 2

Bug Summaries

  1. Security Risk in API Request Logging - The LoggingRoundTripper in backend/utils/trip_logger.go logs the full URL path of GitHub API requests in debug logs. This could leak sensitive information such as private repository names, confidential issue numbers, internal project structure, and query parameters containing tokens when debug logging is enabled in production environments.

  2. Insufficient Error Logging - The GitHub API response logging only captures status codes without including the response body for error cases (non-2xx status codes). This makes debugging API failures difficult as developers cannot see the actual error messages returned by GitHub.

The security risk in request logging is particularly critical as it could potentially expose sensitive organizational data through debug logs.

Comment on lines +13 to +17
// Log the request
slog.Debug("GitHub API Request",
"method", req.Method,
"url_path", req.URL.Path,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The LoggingRoundTripper logs the full URL path of GitHub API requests in debug logs. This could potentially leak sensitive information when debug logging is enabled in production environments.

GitHub API paths can contain sensitive information such as:

  1. Repository names in private organizations
  2. Issue or PR numbers that might be confidential
  3. File paths that could reveal internal project structure
  4. Query parameters that might contain tokens or other sensitive data

Logging the full URL path creates a security risk as these logs might be accessible to unauthorized personnel or could be included in error reports. The fix removes the URL path from debug logs while still maintaining useful information about the request method.

Suggested change
// Log the request
slog.Debug("GitHub API Request",
"method", req.Method,
"url_path", req.URL.Path,
)
// Log the request method only to avoid potential sensitive information leakage
slog.Debug("GitHub API Request",
"method", req.Method,
)

Comment on lines +25 to +37
slog.Debug("GitHub API Response",
"status", resp.Status,
)

if resp.Header != nil {
slog.Debug("GitHub API Rate Limits",
"X-RateLimit-Limit", resp.Header.Get("X-RateLimit-Limit"),
"X-RateLimit-Remaining", resp.Header.Get("X-RateLimit-Remaining"),
"X-RateLimit-Used", resp.Header.Get("X-RateLimit-Used"),
"X-RateLimit-Resource", resp.Header.Get("X-RateLimit-Resource"),
"X-RateLimit-Reset", resp.Header.Get("X-RateLimit-Reset"),
)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The LoggingRoundTripper currently logs the status code of GitHub API responses, but doesn't log the response body when there's an error (non-2xx status code). This makes debugging API errors difficult because developers can't see the actual error message returned by GitHub.

The fix adds code to read and log the response body when a non-2xx status code is received, while ensuring the response body is still available for downstream consumers by creating a new reader with the same content. This significantly improves the debugging experience when GitHub API calls fail.

Note: This implementation requires adding "bytes" to the import statement, which isn't included in this fix.

Suggested change
slog.Debug("GitHub API Response",
"status", resp.Status,
)
if resp.Header != nil {
slog.Debug("GitHub API Rate Limits",
"X-RateLimit-Limit", resp.Header.Get("X-RateLimit-Limit"),
"X-RateLimit-Remaining", resp.Header.Get("X-RateLimit-Remaining"),
"X-RateLimit-Used", resp.Header.Get("X-RateLimit-Used"),
"X-RateLimit-Resource", resp.Header.Get("X-RateLimit-Resource"),
"X-RateLimit-Reset", resp.Header.Get("X-RateLimit-Reset"),
)
}
slog.Debug("GitHub API Response",
"status", resp.Status,
)
if resp.Header != nil {
slog.Debug("GitHub API Rate Limits",
"X-RateLimit-Limit", resp.Header.Get("X-RateLimit-Limit"),
"X-RateLimit-Remaining", resp.Header.Get("X-RateLimit-Remaining"),
"X-RateLimit-Used", resp.Header.Get("X-RateLimit-Used"),
"X-RateLimit-Resource", resp.Header.Get("X-RateLimit-Resource"),
"X-RateLimit-Reset", resp.Header.Get("X-RateLimit-Reset"),
)
}
// Log response body for non-2xx status codes to aid debugging
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
body, err := net.ReadAll(resp.Body)
if err != nil {
slog.Error("Failed to read error response body", "error", err)
} else {
// We need to restore the response body for downstream consumers
resp.Body = net.NopCloser(bytes.NewBuffer(body))
slog.Error("GitHub API Error Response",
"status", resp.Status,
"body", string(body),
)
}
}

@motatoes motatoes merged commit bdf5316 into develop Jul 24, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant