Skip to content

fix: harden VirusTotal error handling, logging, and rate-limit accounting (t147.3)#468

Merged
marcusquinn merged 2 commits intomainfrom
feature/t147.3
Feb 7, 2026
Merged

fix: harden VirusTotal error handling, logging, and rate-limit accounting (t147.3)#468
marcusquinn merged 2 commits intomainfrom
feature/t147.3

Conversation

@marcusquinn
Copy link
Copy Markdown
Owner

Summary

  • Redirect all log functions to stderr to prevent stdout pollution during command substitution
  • Return distinct exit code (2) from vt_request for NotFoundError, enabling callers to distinguish 404 from quota/network errors
  • Fix cmd_scan_file to propagate real API errors instead of treating all failures as "not in database"
  • Count every API request attempt toward rate limit (not just successful ones), preventing quota overruns
  • Replace O(n²) domain dedup loop with associative array lookup
  • Add early jq dependency check in main() for clear error messaging
  • Fix security-helper.sh to scan file directly for file-based skills instead of entire parent directory
  • Fix add-skill-helper.sh: correct return value comment, use resolved path in log message

Analysis

Addresses 9 unresolved review threads from PR #410 (VirusTotal integration):

Severity File Issue Verified
HIGH virustotal-helper.sh:43 Log functions write to stdout, polluting command substitution Yes - all 4 functions confirmed writing to stdout
HIGH virustotal-helper.sh:183 vt_request returns 1 for all errors - no way to distinguish NotFound from QuotaExceeded Yes - single exit code for all error types
HIGH virustotal-helper.sh:266 cmd_scan_file treats all API failures as "not in database" Yes - `
MAJOR security-helper.sh:600 dirname scans entire parent directory for file-based skills Yes - dirname "playwright-skill.md" scans all of tools/browser/
MAJOR virustotal-helper.sh:505 Rate-limit counter only increments on success, failed requests still consume quota Yes - request_count++ after success only
MAJOR virustotal-helper.sh:266 Missing jq dependency guard Yes - jq checked in cmd_status but not before scan commands
MEDIUM add-skill-helper.sh:588 Comment says "returns 1 for threats" but always returns 0 Yes - advisory-only, always returns 0
MEDIUM virustotal-helper.sh:568 O(n²) domain dedup via nested loop Yes - linear scan for each domain
MEDIUM add-skill-helper.sh:616 Log message says virustotal-helper.sh without path Yes - not actionable without full path

Testing

  • bash -n: syntax check passes for all 3 files
  • ShellCheck: zero violations for all 3 files
  • vt_request exit code contract: 0=success, 1=general error, 2=not found

Closes #444

…ting (t147.3)

- Redirect all log functions to stderr to prevent stdout pollution in command substitution
- Return exit code 2 from vt_request for NotFoundError, allowing callers to distinguish 404 from quota/network errors
- Fix cmd_scan_file to propagate real API errors instead of treating all failures as 'not in database'
- Count every API request attempt toward rate limit, not just successful ones
- Replace O(n²) domain dedup loop with associative array lookup
- Add early jq dependency check in main() for clear error messaging
- Fix security-helper.sh to scan file directly for file-based skills instead of entire parent directory
- Fix add-skill-helper.sh: correct return value comment, use resolved path in log message

Addresses 9 review threads (3 high, 3 major, 3 medium) from PR #410.
Closes #444
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 7, 2026

Warning

Rate limit exceeded

@marcusquinn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 16 minutes and 3 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/t147.3

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 and usage tips.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @marcusquinn, 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 enhances the robustness and reliability of the VirusTotal integration within the agent scripts. It addresses several critical issues related to error handling, API rate limit management, and scanning logic, ensuring more accurate reporting and preventing unintended side effects during script execution. The changes aim to make the VirusTotal scanning process more resilient and user-friendly by providing clearer feedback and more precise control over API interactions.

Highlights

  • Improved Logging: All log functions (log_info, log_success, log_warning, log_error) now direct their output to stderr to prevent stdout pollution during command substitution.
  • Granular Error Handling: The vt_request function now returns a distinct exit code (2) specifically for NotFoundError responses from the VirusTotal API, allowing calling functions to differentiate it from general API errors (exit code 1).
  • Accurate API Error Propagation: The cmd_scan_file function has been updated to correctly distinguish between a NotFoundError (file not in VT database) and other genuine API errors (e.g., quota exceeded, network failure), ensuring appropriate error messages and return values.
  • Precise Rate Limit Accounting: The request_count for rate limiting is now incremented for every VirusTotal API request attempt, regardless of whether the request was successful or failed, preventing potential quota overruns.
  • Optimized Domain Deduplication: The O(n²) nested loop used for deduplicating domains in cmd_scan_skill has been replaced with a more efficient associative array lookup, improving performance.
  • Early Dependency Check: An explicit check for the jq dependency has been added to the main() function of virustotal-helper.sh, providing a clear error message if jq is not installed before any scan commands are executed.
  • Targeted File Scanning: The security-helper.sh script now correctly identifies and scans the specific file or its containing directory (if it's a directory-based skill) for VirusTotal checks, rather than always scanning the entire parent directory.
  • Refined Skill Helper Logging: In add-skill-helper.sh, the comment for scan_skill_virustotal's return value has been clarified, and log messages now use the resolved vt_helper path for better actionability.
Changelog
  • .agents/scripts/add-skill-helper.sh
    • Updated the comment for scan_skill_virustotal to clarify that it always returns 0, as VT scans are advisory.
    • Modified the log message for VirusTotal flagged threats to use the vt_helper variable for the script path, improving actionability.
  • .agents/scripts/security-helper.sh
    • Adjusted the cmd_skill_scan function to determine the correct scan_target (file or directory) for VirusTotal scanning, preventing unnecessary directory scans.
  • .agents/scripts/virustotal-helper.sh
    • Redirected all log_info, log_success, log_warning, and log_error functions to stderr to avoid polluting stdout.
    • Modified vt_request to return a distinct exit code (2) when a NotFoundError is received from the VirusTotal API.
    • Updated cmd_scan_file to differentiate between NotFoundError (exit code 2) and other API errors (exit code 1) from vt_request, providing more accurate error reporting.
    • Ensured that the request_count for rate limiting is incremented for every vt_request call, regardless of its success or failure.
    • Replaced the O(n²) domain deduplication logic in cmd_scan_skill with an associative array (domains_seen) for improved performance.
    • Added a jq dependency check at the beginning of the main function to provide an early and clear error message if jq is not installed.
  • TODO.md
    • Updated the status of task t147.3 to 'started'.
    • Added a 'BLOCKED' note to task t135.8.1.
Activity
  • The author, marcusquinn, has addressed 9 unresolved review threads from a previous pull request (feat: add VirusTotal API integration for skill security scanning #410) related to VirusTotal integration.
  • The pull request title and body indicate a focus on hardening error handling, logging, and rate-limit accounting for the VirusTotal functionality.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 7, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 27 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sat Feb 7 19:44:56 UTC 2026: Code review monitoring started
Sat Feb 7 19:44:56 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 27
Sat Feb 7 19:44:56 UTC 2026: Qlty - 0 issues found, auto-formatting applied
Sat Feb 7 19:44:58 UTC 2026: Codacy analysis completed with auto-fixes

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 27
  • VULNERABILITIES: 0

Generated on: Sat Feb 7 19:44:59 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Feb 7, 2026

@marcusquinn marcusquinn merged commit 649654b into main Feb 7, 2026
10 of 11 checks passed
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a number of excellent fixes and hardening measures for the VirusTotal helper script. The changes to error handling, logging, rate-limiting, and performance are all well-implemented and significantly improve the script's robustness and reliability. I have a couple of suggestions to further improve logging consistency by removing stderr suppression within the cmd_scan_skill function. This would allow detailed API errors to be visible by default, enhancing debuggability. Overall, this is a high-quality pull request.

response=$(vt_request "GET" "/files/${sha256}" 2>/dev/null) || {
# Not in VT database -- normal for text files
local vt_exit=0
response=$(vt_request "GET" "/files/${sha256}" 2>/dev/null) || vt_exit=$?
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The 2>/dev/null here suppresses the detailed API error messages that vt_request logs to stderr. Since a major goal of this PR is to improve logging and error handling, it would be better to let these errors be displayed. This would provide more context when an API error occurs, rather than just the generic "API error" message printed later. The caller can still choose to suppress stderr if needed.

Suggested change
response=$(vt_request "GET" "/files/${sha256}" 2>/dev/null) || vt_exit=$?
response=$(vt_request "GET" "/files/${sha256}") || vt_exit=$?

local response=""
response=$(vt_request "GET" "/domains/${domain}" 2>/dev/null) || {
local vt_exit=0
response=$(vt_request "GET" "/domains/${domain}" 2>/dev/null) || vt_exit=$?
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Similar to the file scan, the 2>/dev/null here suppresses detailed error messages from vt_request. Removing it would improve debuggability by showing the actual API error when a domain lookup fails for reasons other than "not found".

Suggested change
response=$(vt_request "GET" "/domains/${domain}" 2>/dev/null) || vt_exit=$?
response=$(vt_request "GET" "/domains/${domain}") || vt_exit=$?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

code-reviews-actioned All review feedback has been actioned

Projects

None yet

Development

Successfully merging this pull request may close these issues.

t147.3: bug: virustotal-helper.sh logging to stdout, poor API error handling

1 participant