fix(ea1): reject footnote-legend '*', bound pre-colon gap, detect YAML block-list and JSON wildcard grants - #447
Open
yashrajp22 wants to merge 2 commits into
Open
Conversation
…ck-list and JSON wildcard grants Fixes #444. Fixes #445. Follow-up to #405/#417. Remaining false positives (#444): - A bare '*' now counts only when it ends the line (optionally ']' and/or a '#' comment), so footnote legends like 'Tools: * = requires auth' no longer fire. Quoted '*' stays unambiguous anywhere on the line. - The gap before the colon is bounded to the same line ([ \t]*:), so a blank line followed by a markdown definition-list ': *' can no longer bridge paragraphs. Detection gaps (#445): - The key may be quoted, catching JSON forms: "tools": ["*"] and "permissions": "*". - New block-list branch catches the idiomatic YAML form (tools: newline '- "*"'), bounded to a single newline with a standalone-star item so markdown lists of bold/italic names cannot collide. - A quoted '*' anywhere in a same-line bracket list now matches (tools: ["search", "*"]). Validated against a 46-case matrix (20 genuine grant forms, 11 new detections, 15 false-positive classes); full suite 2963 passed, ruff check/format clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #405 / #417 (and duplicate #438). #417 correctly bounded the EA1 wildcard-grant regex to a single line and a standalone
*, but an execution-verified edge-case audit of the merged pattern found two remaining false-positive paths and three detection gaps. This PR fixes all five.Fixes #444. Fixes #445. (Systemic paragraph-crossing across all 15 pattern files is tracked separately in #446 — out of scope here.)
Cases and how each is solved
False positives removed (#444)
Case 1 — footnote/legend text after a
Tools:label.The
(?!\*|\w)lookahead rejects**and*word, but a standalone*followed by a space passed — both lines fired EA1/MEDIUM on benign docs.Solution: a bare (unquoted)
*now only counts when it ends the line, optionally closed by]and/or a#comment. A real bare-scalar grant (tools: *,tools: [*],tools: * # allow all) has nothing else after the value; a footnote legend always does. Quoted forms ("*",'*') are unambiguous and keep matching anywhere on the line.Case 2 — blank-line gap before the colon.
#417 bounded the whitespace after the colon, but
\s*:before it still crossed newlines, so a markdown definition-list line two paragraphs later still bridged (matched texttools\n\n: *).Solution:
[ \t]*:— the key and colon must share a line. No real YAML/JSON/TOML syntax breaks a line between key and colon.Detection gaps closed (#445)
Case 3 — JSON quoted keys never matched.
The old prefix required the colon directly after the key word, so the closing quote of a JSON key broke the match — despite JSON being the most common encoding for MCP/agent configs.
Solution: the key may be wrapped in optional quotes:
['\"]?(?:tools?|permissions?)['\"]?.Case 4 — the idiomatic YAML block-list form never matched.
The block-sequence dash was never part of the pattern.
Solution: a second pattern matches a key followed by exactly one newline and a first list item that is a standalone wildcard. A blank line still breaks the match (the #405 cross-heading bridge cannot return), and the standalone-
*lookahead keeps markdown lists (- **Read**,- *note*) out. Later items are intentionally out of scope until seen in practice — matching arbitrary positions across lines widens the false-positive surface.Case 5 — wildcard not in first position of an inline list.
The old pattern required
*immediately after[.Solution: a quoted
*anywhere inside same-line brackets now matches (\[[^\]\r\n]*['\"]\*['\"]). Quoted-only on purpose: markdown link/bold text inside[...]cannot satisfy it, and an unquoted*mid-list in YAML is an alias, not a wildcard.Validation
analyze()flags (re.IGNORECASE | re.MULTILINE): 20 genuine grant forms still detected (quoted/bracketed/bare/no-space/tab/CRLF/uppercase/comments/allowed_toolssubstring), 11 new detections, 15 false-positive classes rejected (including all EA1 wildcard-tool-access pattern crosses blank lines and matches markdown bold syntax Affected rule: EA1 "Unrestricted Tool Access" Affected file: src/skillspector/nodes/analyzers/static_patterns_excessive_agency.py, line 45 #405/fix(ea1): bound wildcard-tool-access match to a single line and a sta… #417 regression cases).pytest tests/ -m "not integration and not provider"— 2,963 passed, 14 skipped, 4 xfailed, 0 failures.tests/nodes/analyzers/test_ea1_wildcard_line_boundary.py(footnote legend ×2, pre-colon gap, bare+comment, YAML block quoted/bare/zero-indent, JSON list/scalar key, inline not-first, markdown bold dash-list negative, blank-line-before-dash negative).ruff checkandruff format --checkclean.Risk
tools: [\n "*"\n]) and wildcards in later block-list items.