-
Notifications
You must be signed in to change notification settings - Fork 32
Fix health check ping fallback and implement healthy-auth-expired status #110
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
Conversation
…er service - Remove update_auth_tokens() function from build_and_run.sh to separate concerns - Remove automatic token refresher startup from deployment script - Add standalone token refresher service with MCP config generation - Add token_refresher.pid to .gitignore - Add support for no-auth services in token refresher alongside egress token services - Clean up emoji usage in logging for better compatibility 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Add HealthStatus enum with Pydantic model for type-safe status management - Fix nginx service to include services with expired auth tokens - Update React frontend to display 'Healthy (Auth Expired)' status with orange styling - Replace hardcoded status strings throughout codebase with constants - Add comprehensive health check ping fallback for expired authentication - Improve service availability by including reachable services regardless of auth status
- Fix Roo Code configuration file name to mcp_settings.json (with underscore) - Add comprehensive token refresh service integration documentation - Remove emojis for professional appearance - Remove multi-gateway support section - Add symbolic link setup option for automatic configuration updates - Enhance troubleshooting with token refresh service specific guidance
List of (filepath, token_data) tuples for expiring tokens | ||
""" | ||
if not OAUTH_TOKENS_DIR.exists(): | ||
logger.error(f"OAuth tokens directory not found: {OAUTH_TOKENS_DIR}") |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
sensitive data (password)
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 21 days ago
To remediate this security issue, we should avoid logging the full path of the OAuth tokens directory in cleartext. The best approach is to log a generic error message (e.g., "OAuth tokens directory not found") without including the potentially sensitive path. This change should be made only to the log statement in question, on line 149 within the _get_expiring_tokens
function. No additional imports or code structure changes are required. Only the logging statement should be changed.
-
Copy modified line R149
@@ -146,7 +146,7 @@ | ||
List of (filepath, token_data) tuples for expiring tokens | ||
""" | ||
if not OAUTH_TOKENS_DIR.exists(): | ||
logger.error(f"OAuth tokens directory not found: {OAUTH_TOKENS_DIR}") | ||
logger.error("OAuth tokens directory not found") | ||
return [] | ||
|
||
current_time = time.time() |
os.rename(temp_path, config_file) | ||
os.chmod(config_file, 0o600) | ||
|
||
logger.info(f"Generated VS Code MCP config: {config_file}") |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
sensitive data (password)
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 21 days ago
Sensitive information including the location and name of files containing tokens and credentials should not be logged at an INFO (or higher) level since logs may be accessed by users or services without a strict need-to-know. Here, logging the path to a generated config file within the .oauth-tokens
directory at line 680 potentially exposes the location of sensitive files. The logging statement should be reworded to remove the sensitive file path.
Best practice fix:
- Change the log message at line 680 to avoid including
config_file
(the full path). - The message can simply indicate success, e.g.
"VS Code MCP config generated successfully"
. - If file path needs to be logged for troubleshooting, use DEBUG level (where logs are less likely to be exposed) and log a sanitized/abstracted version if possible.
- No changes to program functionality.
File/Region to change:
credentials-provider/token_refresher.py
— line 680
No imports or extra definitions are needed.
-
Copy modified line R680
@@ -677,7 +677,7 @@ | ||
os.rename(temp_path, config_file) | ||
os.chmod(config_file, 0o600) | ||
|
||
logger.info(f"Generated VS Code MCP config: {config_file}") | ||
logger.info("VS Code MCP config generated successfully") | ||
logger.debug(f"VS Code config written to: {config_file.absolute()}") | ||
return True | ||
|
os.chmod(config_file, 0o600) | ||
|
||
logger.info(f"Generated VS Code MCP config: {config_file}") | ||
logger.debug(f"VS Code config written to: {config_file.absolute()}") |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
sensitive data (password)
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 21 days ago
To fix the issue, we should ensure that sensitive path information—such as the full path to credential files in the .oauth-tokens
directory—is not logged at an INFO level, and preferably not at all. In this context, the log on line 681 (logger.debug(f"VS Code config written to: {config_file.absolute()}")
) is at DEBUG, but the problematic INFO log is on line 680 (logger.info(f"Generated VS Code MCP config: {config_file}")
). Both lines potentially leak path details.
The best fix is to avoid logging sensitive file paths. If confirmation of successful operation is still desired, either:
- Only log a generic message (e.g., "VS Code MCP config generated successfully") without including the path; or
- If including the file/location is absolutely necessary for debugging, limit this to DEBUG level and redact the sensitive part (e.g., replacing directory/usernames with
<redacted>
or only showing the filename, not the full path).
Specifically, update the logging statement(s) within the _generate_vscode_config
function after writing the config file:
- Change or remove the INFO log(s) that contain the config file path.
- If feasible, leave a less specific INFO message, and only log the full path at DEBUG level (with a warning in the comment).
- Optionally, if you must report the path at DEBUG, only show the filename portion:
config_file.name
.
-
Copy modified lines R680-R681
@@ -677,8 +677,8 @@ | ||
os.rename(temp_path, config_file) | ||
os.chmod(config_file, 0o600) | ||
|
||
logger.info(f"Generated VS Code MCP config: {config_file}") | ||
logger.debug(f"VS Code config written to: {config_file.absolute()}") | ||
logger.info("Generated VS Code MCP config.") # File path omitted for security | ||
logger.debug(f"VS Code config written to: {config_file.absolute()}") # CAUTION: Reveals sensitive path | ||
return True | ||
|
||
except Exception as e: |
continue | ||
|
||
config["mcpServers"][server_key] = server_config | ||
logger.debug(f"Added no-auth service {server_key} to Roocode config") |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
sensitive data (password)
This expression logs
sensitive data (password)
This expression logs
sensitive data (password)
This expression logs
sensitive data (password)
This expression logs
sensitive data (password)
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 21 days ago
The best fix is to avoid logging user-controlled (and potentially sensitive) information unsanitized. In this case, rather than logging the raw server_key
(which is derived from an untrusted path string), we should log only non-sensitive metadata or, if needed, a redacted/hashed representation. The minimal and safest fix, with no functional impact, is simply to remove the value from the log message, or replace it with a generic statement. Alternatively, if it is important to trace which services are added, we could log the fact that a service was added—perhaps logging the index number or a redacted/hashed summary. Since server_key
comes from an untrusted source, and for this trace message its specific contents are not essential, the best way is simply to drop the {server_key}
from the debug message.
Edit in credentials-provider/token_refresher.py
:
- On line 748, replace:
logger.debug(f"Added no-auth service {server_key} to Roocode config")
with:
logger.debug("Added no-auth service to Roocode config")
No imports or new method definitions are required.
-
Copy modified line R748
@@ -745,7 +745,7 @@ | ||
continue | ||
|
||
config["mcpServers"][server_key] = server_config | ||
logger.debug(f"Added no-auth service {server_key} to Roocode config") | ||
logger.debug("Added no-auth service to Roocode config") | ||
|
||
# Write JSON to temp file | ||
json.dump(config, temp_file, indent=2) |
os.rename(temp_path, config_file) | ||
os.chmod(config_file, 0o600) | ||
|
||
logger.info(f"Generated Roocode MCP config: {config_file}") |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
sensitive data (password)
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 21 days ago
To fix this issue, the code should avoid logging the full path to the generated .oauth-tokens/mcp.json
config file at INFO
level. Instead, you can:
- Log only the filename, not the directory (e.g., "Generated Roocode MCP config as
mcp.json
"), or - Use a generic message such as "Generated Roocode MCP config" without mentioning the location.
If precise debugging information (such as the full file path) is still needed for diagnostics, consider moving such details to theDEBUG
level, assuming debug logs are only available in controlled environments.
Edit filecredentials-provider/token_refresher.py
: - On line 757, change the log statement to avoid directly exposing the sensitive file path at
INFO
. - You may optionally preserve the full path in the
DEBUG
log (line 758) if needed.
No new imports or definitions are required.
-
Copy modified line R757
@@ -754,7 +754,7 @@ | ||
os.rename(temp_path, config_file) | ||
os.chmod(config_file, 0o600) | ||
|
||
logger.info(f"Generated Roocode MCP config: {config_file}") | ||
logger.info("Generated Roocode MCP config successfully.") | ||
logger.debug(f"Roocode config written to: {config_file.absolute()}") | ||
return True | ||
|
os.chmod(config_file, 0o600) | ||
|
||
logger.info(f"Generated Roocode MCP config: {config_file}") | ||
logger.debug(f"Roocode config written to: {config_file.absolute()}") |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
sensitive data (password)
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 21 days ago
To address this issue, logging of the absolute path to the MCP config file should be avoided. Retain only log messages that do not include potentially sensitive information such as file system paths. You can keep a generic message (e.g., "Generated Roocode MCP config file.") or, if you wish to indicate location, only log the filename (not the absolute path), which removes most risk—though, even then, avoid logging any variable part of the path.
The required changes are:
- Edit credentials-provider/token_refresher.py at line 758 to remove or redact the path information. You might log only the filename using
config_file.name
instead of.absolute()
, or just omit the path entirely from the info-level log. - No extra imports are needed for this change.
-
Copy modified line R757
@@ -754,7 +754,7 @@ | ||
os.rename(temp_path, config_file) | ||
os.chmod(config_file, 0o600) | ||
|
||
logger.info(f"Generated Roocode MCP config: {config_file}") | ||
logger.info("Generated Roocode MCP config file.") | ||
logger.debug(f"Roocode config written to: {config_file.absolute()}") | ||
return True | ||
|
force_refresh: If True, refresh all tokens regardless of expiration | ||
""" | ||
logger.info("Starting token refresh cycle...") | ||
logger.debug(f"Token directory: {OAUTH_TOKENS_DIR.absolute()}") |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
sensitive data (password)
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 21 days ago
To fix the problem, we should avoid logging the full, absolute path of the token storage directory. Instead, log only non-sensitive, high-level information, such as the directory name or a generic statement indicating which operation is under way. If location information is essential for diagnosing errors, the code should provide a sanitized or truncated version of the path that does not reveal directory structure or user information.
Specifically for this code:
- Remove or redact the log message at line 783 (
logger.debug(f"Token directory: {OAUTH_TOKENS_DIR.absolute()}")
). - If keeping the log message is valuable, use something generic and non-sensitive (e.g.,
"Token directory resolved"
or"Token directory set (path not shown for security)"
), or log just the directory name (OAUTH_TOKENS_DIR.name
) rather than its absolute path. - No new imports are needed.
-
Copy modified line R783
@@ -780,7 +780,7 @@ | ||
force_refresh: If True, refresh all tokens regardless of expiration | ||
""" | ||
logger.info("Starting token refresh cycle...") | ||
logger.debug(f"Token directory: {OAUTH_TOKENS_DIR.absolute()}") | ||
logger.debug("Token directory set (path omitted for security).") | ||
|
||
# Find expiring tokens | ||
if force_refresh: |
logger.info("OAuth Token Refresher Service Starting") | ||
logger.info(f"Check interval: {args.interval} seconds") | ||
logger.info(f"Expiry buffer: {args.buffer} seconds ({args.buffer / 3600:.1f} hours)") | ||
logger.info(f"OAuth tokens directory: {OAUTH_TOKENS_DIR}") |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
This autofix suggestion was applied.
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 21 days ago
To fix this problem, the log entry at line 1026 should avoid exposing the full path to the .oauth-tokens
directory. Instead, the code should log only a non-sensitive part, such as a generic label ("(path hidden)") or just the directory name, without revealing the parent directories.
The fix requires modifying only line 1026 in credentials-provider/token_refresher.py
, changing the log message to avoid logging the full OAUTH_TOKENS_DIR
path. For troubleshooting, you can log only the directory name (OAUTH_TOKENS_DIR.name
), or a placeholder to indicate the token directory is configured. No new imports or method definitions are needed.
-
Copy modified line R1026
@@ -1023,7 +1023,7 @@ | ||
logger.info("OAuth Token Refresher Service Starting") | ||
logger.info(f"Check interval: {args.interval} seconds") | ||
logger.info(f"Expiry buffer: {args.buffer} seconds ({args.buffer / 3600:.1f} hours)") | ||
logger.info(f"OAuth tokens directory: {OAUTH_TOKENS_DIR}") | ||
logger.info("OAuth tokens directory is configured") | ||
logger.info("=" * 60) | ||
|
||
# Set up signal handlers and PID file for continuous mode |
…ensitive information Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
…ensitive information Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Summary
Problem
The health check ping fallback was working correctly - when authentication failed (401), the system would fall back to a ping check without auth to determine if the server was reachable. However, services with "healthy-auth-expired" status were being excluded from the nginx configuration because the logic only included servers with status exactly equal to "healthy".
Solution
Core Fixes
HealthStatus.is_healthy()
methodHealthStatus
enum to replace hardcoded strings throughout the codebaseFrontend Updates
Documentation Updates
Testing
Files Changed
Backend:
registry/constants.py
(new) - HealthStatus enum with Pydantic modelregistry/core/nginx_service.py
- Fixed inclusion logic for expired auth servicesregistry/health/service.py
- Replaced hardcoded strings with constantsFrontend:
frontend/src/components/ServerCard.tsx
- Added new status support and stylingfrontend/src/pages/Dashboard.tsx
- Updated Server interfacefrontend/src/hooks/useServerStats.ts
- Updated Server interfaceDocumentation:
docs/ai-coding-assistants-setup.md
- Enhanced with token refresh integrationdocs/auth.md
- Added token refresh service referencesdocs/jwt-token-vending.md
- Added integration documentationdocs/token-refresh-service.md
(new) - Comprehensive token refresh documentation