Skip to content

Fix proactive AWS credential refresh silently skipping all credentials - #580

Open
5Devanshu wants to merge 1 commit into
Arvo-AI:mainfrom
5Devanshu:bugfix/aws-credential-refresh-cache-key
Open

Fix proactive AWS credential refresh silently skipping all credentials#580
5Devanshu wants to merge 1 commit into
Arvo-AI:mainfrom
5Devanshu:bugfix/aws-credential-refresh-cache-key

Conversation

@5Devanshu

@5Devanshu 5Devanshu commented Jul 6, 2026

Copy link
Copy Markdown

Problem

The proactive STS credential refresh task in server/utils/aws/credential_refresh.py
never refreshes any credentials.

Cache keys are built in aws_sts_client.py as:

f"{uid}:{role_arn}:{external_id}:{policy_hash}"

The refresh task tried to recover the role ARN from each key with
k.split(":")[0]. Because AWS ARNs themselves contain colons
(arn:aws:iam::123456789012:role/MyRole), split(":")[0] returns the
uid, not the ARN. The later check if role_arn not in expiring_role_arns
then compares a real ARN against a set of user IDs, which never matches —
so every credential is skipped and the task silently does nothing. No error
is raised, so the failure is invisible in normal operation.

Fix

Instead of parsing the ARN back out of the key, reconstruct the deterministic
prefix from the DB row and match with startswith():

cache_key_prefix = f"{user_id}:{role_arn}:{external_id}:"
if not any(k.startswith(cache_key_prefix) for k in expiring_cache_keys):
    skipped += 1
    continue

The trailing : anchors the match to the field boundary, so a role such as
.../role/Admin cannot accidentally match .../role/AdminReadOnly. Because
policy_hash is the final field, the prefix correctly matches all cached
policy variants for the same connection.

Testing

Adds server/tests/utils/test_credential_refresh.py with two tests:

  • test_expiring_connection_is_refreshed — a near-expiry cache entry triggers
    a re-assume. Fails on current main, passes with this fix.
  • test_prefix_does_not_match_longer_role — proves the Admin prefix does not
    match AdminReadOnly.

Both pass locally.

Scope

This fixes the matching only. The task re-assumes the full-policy variant, so
restricted (session_policy) cache entries are still not proactively refreshed
— that's pre-existing behavior and out of scope here, but could be a follow-up.

Summary by CodeRabbit

  • Bug Fixes

    • Improved AWS credential refresh behavior so only the intended connection is refreshed when credentials are nearing expiration.
    • Prevented overlapping role names from triggering the wrong refresh action.
  • Documentation

    • Clarified GitHub MCP tool usage guidance, including file size limits and update requirements for uploaded files.
  • Tests

    • Added coverage for credential refresh behavior, including expiration handling and role-matching accuracy.

Cache keys are {uid}:{role_arn}:{external_id}:{policy_hash}, but the
refresh task recovered the ARN via split(':')[0], which returns the
user ID since ARNs contain colons. This caused proactive refresh to
silently skip every credential. Reconstruct the key prefix and match
with startswith() instead. Adds regression tests.
@5Devanshu
5Devanshu requested a review from a team as a code owner July 6, 2026 22:02
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Modified refresh_aws_credentials to match active AWS connections against expiring cache entries using a cache-key prefix check (user_id, role_arn, external_id) instead of a derived role ARN set, added corresponding unit tests, and updated GitHub skill documentation with MCP file-operation size and content-retention constraints.

Changes

AWS Credential Refresh Prefix Matching

Layer / File(s) Summary
Cache-key prefix matching logic
server/utils/aws/credential_refresh.py
Removes the derived expiring_role_arns set and instead builds a cache_key_prefix per connection row to check against expiring_cache_keys via prefix matching before refreshing.
Prefix matching tests
server/tests/utils/test_credential_refresh.py
New test module validates refresh/skip counts and assume_workspace_role call arguments, including a case confirming that an AdminReadOnly role key does not falsely match an Admin prefix.

Estimated code review effort: 3 (Moderate) | ~20 minutes

GitHub Skill MCP Tools Documentation

Layer / File(s) Summary
MCP file operation constraints doc update
server/chat/backend/agent/skills/integrations/github/SKILL.md
Expands MCP Tools guidance with a 50 KB per-file size cap for create_or_update_file/push_files and a minimum 50% content-retention rule for files over 10 KB.

Estimated code review effort: 1 (Trivial) | ~3 minutes

Sequence Diagram(s)

sequenceDiagram
    participant Task as refresh_aws_credentials
    participant Cache as _credential_cache
    participant DB as Database
    participant STS as assume_workspace_role

    Task->>Cache: read expiring cache keys within refresh window
    Task->>DB: query active AWS connections
    DB-->>Task: return user_id, role_arn, external_id rows
    loop for each connection row
        Task->>Task: build cache_key_prefix from user_id, role_arn, external_id
        Task->>Cache: check if any expiring key starts with prefix
        alt prefix matches
            Task->>STS: assume_workspace_role(role_arn, external_id, workspace_id, region, user_id)
            STS-->>Task: refreshed credentials
        else no match
            Task->>Task: skip row
        end
    end
    Task-->>Task: return refreshed and skipped counts
Loading

Suggested reviewers: OlivierTrudeau

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main fix to proactive AWS credential refresh skipping credentials.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

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

@arvo-ai-staging arvo-ai-staging Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Aurora Risk Review

Verdict: SAFE

No risks identified. This change looks safe to ship.


Aurora reviews PRs for incident prevention.

@sonarqubecloud

sonarqubecloud Bot commented Jul 6, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/chat/backend/agent/skills/integrations/github/SKILL.md`:
- Around line 49-50: Add a blank line after the “### MCP Tools” heading in
SKILL.md so the list starts separated from the heading and satisfies
markdownlint MD022. Update the markdown around the “MCP Tools” section by
inserting a single empty line before the “- Files:” list item, keeping the rest
of the section unchanged.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: dcbb2dd2-cba5-417b-90fb-4ea760592a5f

📥 Commits

Reviewing files that changed from the base of the PR and between 816f677 and b2ab6ac.

📒 Files selected for processing (3)
  • server/chat/backend/agent/skills/integrations/github/SKILL.md
  • server/tests/utils/test_credential_refresh.py
  • server/utils/aws/credential_refresh.py

Comment on lines 49 to 50
### MCP Tools (for direct GitHub API operations beyond RCA)
- Files: `get_file_contents`, `create_or_update_file`, `push_files`, `get_repository_tree`

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a blank line after the heading.

markdownlint-cli2 flags MD022 here: the ### MCP Tools heading is immediately followed by the list item, so it is not surrounded by blank lines. Insert one blank line after Line 49 to keep the docs check clean.

♻️ Proposed fix
 ### MCP Tools (for direct GitHub API operations beyond RCA)
+
 - Files: `get_file_contents`, `create_or_update_file`, `push_files`, `get_repository_tree`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### MCP Tools (for direct GitHub API operations beyond RCA)
- Files: `get_file_contents`, `create_or_update_file`, `push_files`, `get_repository_tree`
### MCP Tools (for direct GitHub API operations beyond RCA)
- Files: `get_file_contents`, `create_or_update_file`, `push_files`, `get_repository_tree`
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 49-49: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/chat/backend/agent/skills/integrations/github/SKILL.md` around lines
49 - 50, Add a blank line after the “### MCP Tools” heading in SKILL.md so the
list starts separated from the heading and satisfies markdownlint MD022. Update
the markdown around the “MCP Tools” section by inserting a single empty line
before the “- Files:” list item, keeping the rest of the section unchanged.

Source: Linters/SAST tools

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