NVIDIA / NVIDIA/SkillSpector

[BUG] Rate-limited providers silently lose analyzer coverage: max_concurrency=10 hardcoded, 429 batches dropped without retry, partial LLM pass not flagged

Open
#303 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
17.9k
Forks
1.5k
Avg merge
5d 10h
Merged PRs (30d)
66

Description

Summary

On a rate-limited provider (typical free tier), arun_batches bursts up to a hardcoded max_concurrency=10 and drops any 429'd batch ("logged and omitted from the result") with no retry/backoff. There is no way to lower the concurrency or make the client respect the provider's RPM/TPM. The result is a scan that silently loses analyzer coverage while still emitting a full risk_assessment — including losing the security-critical semantic_security_discovery batch, so a genuinely malicious skill can read as clean.

This is distinct from #290 (provider unavailable): here the provider is available and answering, but throttling, and the partial result is not surfaced as such.

Evidence

Provider openai pointed at Gemini's OpenAI-compatible endpoint, free tier (5 RPM):

WARNING [skillspector.nodes.analyzers.semantic_security_discovery] semantic_security_discovery failed:
Error code: 429 - ... 'quotaId': 'GenerateRequestsPerMinutePerProjectPerModel-FreeTier', 'quotaValue': '5' ...

metadata.llm_calls_attempted: 4, llm_calls_succeeded: 3, yet risk_assessment.severity is emitted normally and issues: 0. On a known-malicious test skill (natural-language exfiltration of ~/.config/gh/hosts.yml), the dropped batch was exactly the analyzer that catches it — the scan reported LOW/clean.

Same pattern on Groq free tier: the ~33k-token semantic_security_discovery prompt exceeds the free TPM cap → 413 → dropped → clean-looking report.

Why the current design makes this invisible

  1. max_concurrency=10 is a fixed default in arun_batches; nothing threads a lower value or reads an env/flag. Ten parallel requests against a 5 RPM budget guarantee 429s.
  2. 429s are caught per-batch and omitted; there is no retry honoring Retry-After.
  3. llm_calls_succeeded < llm_calls_attempted is recorded in metadata but the risk assessment does not treat a partial LLM pass as degraded, so downstream consumers see a normal verdict.

Requests (any subset helps)

  1. Configurable concurrency — an env var / CLI flag (e.g. SKILLSPECTOR_MAX_LLM_CONCURRENCY) so users on rate-limited tiers can serialize.
  2. Retry with backoff on 429/RESOURCE_EXHAUSTED, honoring Retry-After, before giving up on a batch.
  3. Surface incompleteness in the verdict: when any batch is dropped, mark the report degraded / refuse to assert a clean risk_assessment — same failure mode #290 guards against, one step earlier. A metadata flag like llm_batches_dropped: N would let callers gate on it.

Happy to send a PR for (1) and (3) if the direction is agreeable.

Environment

SkillSpector (current main), SKILLSPECTOR_PROVIDER=openai against generativelanguage.googleapis.com/v1beta/openai/ and api.groq.com/openai/v1, free tiers.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the arun_batches entry point and trace how 429 or RESOURCE_EXHAUSTED responses are logged, omitted, and reflected in llm_calls_attempted and llm_calls_succeeded. Then follow risk_assessment construction to determine where configurable concurrency, retry behavior, and degraded verdict metadata belong; done means rate-limited batches are not silently presented as a complete clean scan.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
ai, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.