t1412.2: Scoped short-lived GitHub tokens for worker agents#3094
t1412.2: Scoped short-lived GitHub tokens for worker agents#3094marcusquinn merged 1 commit intomainfrom
Conversation
Implement worker-token-helper.sh for creating minimal-permission, short-lived GitHub tokens for headless worker sessions. Reduces blast radius if a worker is compromised via prompt injection. Two token strategies (tried in priority order): 1. GitHub App installation token — enforced by GitHub, repo-scoped, 1h TTL 2. Delegated token — uses existing gh auth token with advisory scoping Token lifecycle: create (with audit log) -> pass via env -> revoke after session. Token files use 600 permissions and are overwritten before deletion. Integration: - cron-dispatch.sh: creates scoped token before session, revokes after - headless-dispatch.md: full documentation with setup guide - prompt-injection-defender.md: credential isolation defense layer docs - opsec.md: added credential isolation as layer 4 mitigation Closes #3072
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly bolsters the security posture of headless worker agents by introducing a system for generating and managing scoped, short-lived GitHub tokens. This change minimizes the potential impact of a security breach by ensuring that worker agents operate with only the necessary permissions for a limited duration, thereby reducing the blast radius of any compromised credentials. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Sat Mar 7 12:27:23 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
|
There was a problem hiding this comment.
Code Review
This pull request introduces a robust mechanism for creating scoped, short-lived GitHub tokens for worker agents, which is a significant security improvement. While the overall design aims to enhance security, the new utility script worker-token-helper.sh contains critical and high-severity vulnerabilities related to improper input validation. Specifically, the revoke and validate commands are vulnerable to path traversal, potentially allowing arbitrary file overwrite/deletion and arbitrary file read. Additionally, the create command is vulnerable to arithmetic injection via the --ttl parameter, which could lead to arbitrary command execution. These issues require strict input validation and ensuring file operations are restricted to the intended directory. Furthermore, the consistent use of 2>/dev/null to suppress command output in the shell scripts hides crucial error information, making debugging difficult. It is recommended to remove this suppression to improve error visibility.
| dd if=/dev/urandom bs=64 count=1 2>/dev/null | head -c 64 >"$token_file" 2>/dev/null || true | ||
| rm -f "$token_file" |
There was a problem hiding this comment.
The revoke command takes a --token-file argument and performs a secure deletion (overwriting with random data using dd and then removing with rm) without validating that the path is within the intended tokens directory. This allows an attacker who can execute the script to overwrite and delete arbitrary files on the system, leading to a critical denial-of-service or system compromise if run with elevated privileges.
| ;; | ||
| --ttl | -t) | ||
| ttl="$2" | ||
| if ((ttl > MAX_TTL)); then |
There was a problem hiding this comment.
The --ttl argument is used directly in a Bash arithmetic context ((ttl > MAX_TTL)) without prior validation. Bash arithmetic evaluation is susceptible to command injection if the variable contains a specially crafted expression (e.g., a[$(id>&2)0]). This allows an attacker to execute arbitrary commands in the context of the script.
|
|
||
| # Validate token against GitHub API (without exposing the value) | ||
| local token | ||
| token=$(read_token_file "$token_file") || return 1 |
There was a problem hiding this comment.
| response=$(curl -sf -X POST \ | ||
| "https://api.github.com/app/installations/${installation_id}/access_tokens" \ | ||
| -H "Authorization: Bearer ${jwt}" \ | ||
| -H "Accept: application/vnd.github+json" \ | ||
| -H "X-GitHub-Api-Version: 2022-11-28" \ | ||
| -d "$request_body" 2>/dev/null) || { | ||
| log_token "WARN" "GitHub App token creation failed (API error)" | ||
| return 1 | ||
| } |
There was a problem hiding this comment.
Suppressing curl's stderr with 2>/dev/null hides critical information when the GitHub API call fails. Error messages from curl (e.g., network issues, DNS problems) or error responses from the API (which curl -f would print to stderr) are essential for debugging. The || block handles the failure, but the cause of the failure remains unknown.
| response=$(curl -sf -X POST \ | |
| "https://api.github.com/app/installations/${installation_id}/access_tokens" \ | |
| -H "Authorization: Bearer ${jwt}" \ | |
| -H "Accept: application/vnd.github+json" \ | |
| -H "X-GitHub-Api-Version: 2022-11-28" \ | |
| -d "$request_body" 2>/dev/null) || { | |
| log_token "WARN" "GitHub App token creation failed (API error)" | |
| return 1 | |
| } | |
| response=$(curl -sf -X POST \ | |
| "https://api.github.com/app/installations/${installation_id}/access_tokens" \ | |
| -H "Authorization: Bearer ${jwt}" \ | |
| -H "Accept: application/vnd.github+json" \ | |
| -H "X-GitHub-Api-Version: 2022-11-28" \ | |
| -d "$request_body") || { | |
| log_token "WARN" "GitHub App token creation failed (API error)" | |
| return 1 | |
| } |
References
- Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.
| repo_slug=$(git -C "$workdir" remote get-url origin 2>/dev/null | | ||
| sed -E 's|.*github\.com[:/]||; s|\.git$||' || true) |
There was a problem hiding this comment.
The use of 2>/dev/null here suppresses potentially useful error messages from git. If git remote get-url origin fails for reasons other than the remote not existing (e.g., git not in PATH, or not a git repository), those errors will be hidden, making debugging more difficult. The || true already prevents the script from exiting on failure.
| repo_slug=$(git -C "$workdir" remote get-url origin 2>/dev/null | | |
| sed -E 's|.*github\.com[:/]||; s|\.git$||' || true) | |
| repo_slug=$(git -C "$workdir" remote get-url origin | | |
| sed -E 's|.*github\.com[:/]||; s|\.git$||' || true) |
References
- Avoid blanket suppression of errors with '2>/dev/null' to ensure that diagnostic information remains visible for debugging, especially when '|| true' is used to handle failures.
| fi | ||
|
|
||
| if [[ -n "$repo_slug" ]]; then | ||
| worker_token_file=$("$TOKEN_HELPER" create --repo "$repo_slug" --ttl "$timeout" 2>/dev/null) || { |
There was a problem hiding this comment.
Suppressing stderr from "$TOKEN_HELPER" with 2>/dev/null hides valuable debugging information if token creation fails. The helper script provides detailed logs on stderr. Allowing these logs to be displayed would make it easier to diagnose issues with token creation (e.g., misconfiguration, API errors). The failure is already handled gracefully by the || { ... } block.
| worker_token_file=$("$TOKEN_HELPER" create --repo "$repo_slug" --ttl "$timeout" 2>/dev/null) || { | |
| worker_token_file=$("$TOKEN_HELPER" create --repo "$repo_slug" --ttl "$timeout") || { |
References
- Avoid using '2>/dev/null' to suppress command errors, as it can hide important diagnostic information needed for debugging authentication, syntax, or system issues.
|
|
||
| # Revoke scoped worker token (t1412.2) | ||
| if [[ -n "$worker_token_file" ]] && [[ -x "$TOKEN_HELPER" ]]; then | ||
| "$TOKEN_HELPER" revoke --token-file "$worker_token_file" 2>/dev/null || true |
There was a problem hiding this comment.
Suppressing stderr from "$TOKEN_HELPER" revoke with 2>/dev/null can hide errors during token revocation. While the script continues on failure due to || true, seeing the error message from the helper script could be important for diagnosing persistent issues.
| "$TOKEN_HELPER" revoke --token-file "$worker_token_file" 2>/dev/null || true | |
| "$TOKEN_HELPER" revoke --token-file "$worker_token_file" || true |
References
- Avoid using '2>/dev/null' to suppress command errors, as it can hide important diagnostic information needed for debugging authentication, syntax, or system issues.
| app_id=$(jq -r '.app_id // empty' "$APP_CONFIG" 2>/dev/null) | ||
| private_key_path=$(jq -r '.private_key_path // empty' "$APP_CONFIG" 2>/dev/null) | ||
| installation_id=$(jq -r '.installation_id // empty' "$APP_CONFIG" 2>/dev/null) |
There was a problem hiding this comment.
Using 2>/dev/null with jq here suppresses errors if the configuration file ($APP_CONFIG) is malformed or unreadable. Since file existence is checked earlier, any error from jq would indicate a problem with the file's content or permissions. Displaying these errors would aid in debugging configuration issues. The // empty syntax in jq already handles missing keys gracefully.
| app_id=$(jq -r '.app_id // empty' "$APP_CONFIG" 2>/dev/null) | |
| private_key_path=$(jq -r '.private_key_path // empty' "$APP_CONFIG" 2>/dev/null) | |
| installation_id=$(jq -r '.installation_id // empty' "$APP_CONFIG" 2>/dev/null) | |
| app_id=$(jq -r '.app_id // empty' "$APP_CONFIG") | |
| private_key_path=$(jq -r '.private_key_path // empty' "$APP_CONFIG") | |
| installation_id=$(jq -r '.installation_id // empty' "$APP_CONFIG") |
References
- Avoid suppressing stderr with '2>/dev/null' on file operations like 'jq' reads, as it can mask important issues such as malformed files or permission errors, making debugging difficult.
| token_file=$(create_app_token "$repo" "$permissions" "$ttl" 2>/dev/null) && { | ||
| log_token "INFO" "Strategy: GitHub App installation token (enforced scoping)" | ||
| printf '%s' "$token_file" | ||
| return 0 | ||
| } |
There was a problem hiding this comment.
Suppressing stderr from create_app_token with 2>/dev/null prevents any of its diagnostic logs from being displayed. Since create_app_token contains important logging for debugging its internal steps (like JWT generation and API calls), these logs should be visible when this strategy is attempted.
| token_file=$(create_app_token "$repo" "$permissions" "$ttl" 2>/dev/null) && { | |
| log_token "INFO" "Strategy: GitHub App installation token (enforced scoping)" | |
| printf '%s' "$token_file" | |
| return 0 | |
| } | |
| token_file=$(create_app_token "$repo" "$permissions" "$ttl") && { | |
| log_token "INFO" "Strategy: GitHub App installation token (enforced scoping)" | |
| printf '%s' "$token_file" | |
| return 0 | |
| } |
References
- Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.



Summary
worker-token-helper.sh— scoped, short-lived GitHub token lifecycle management for headless worker agentscron-dispatch.shdispatch flowWhat this does
Each headless worker session now receives a minimal-permission GitHub token scoped to the target repo only, with a configurable TTL (default 1h). This limits blast radius if a worker is compromised via prompt injection — the attacker can only access the target repo with
contents:write,pull_requests:write, andissues:writepermissions.Two token strategies (tried in priority order):
Files changed
.agents/scripts/worker-token-helper.sh— token lifecycle (create, validate, revoke, cleanup, status).agents/scripts/cron-dispatch.sh— creates scoped token before dispatch, revokes after.agents/tools/ai-assistants/headless-dispatch.md— full scoped token documentation.agents/tools/security/prompt-injection-defender.md— credential isolation defense layer.agents/tools/security/opsec.md— added credential isolation as layer 4 mitigation.gitignore— exception for worker-token-helper.sh (not a credential file)Security model
Testing
worker-token-helper.sh help— displays usageworker-token-helper.sh status— shows configuration and active tokensworker-token-helper.sh create --repo owner/repo --ttl 60— creates delegated token (tested)worker-token-helper.sh validate --token-file <path>— validates against GitHub API (tested)worker-token-helper.sh revoke --token-file <path>— securely deletes token files (tested)Closes #3072