| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
Expand the skill-scanner with a new check_structural_attacks() function that detects attack vectors beyond text content: symlinks that resolve outside the skill directory, YAML frontmatter hooks that execute shell commands automatically, !command pre-prompt injection that runs at template expansion time, test files that auto-execute via pytest or Jest discovery, npm lifecycle hooks in bundled package.json files, and PNG metadata text that can inject instructions into multimodal LLMs. Also adds Unicode Tag character detection (U+E0000 block) to the obfuscation checks — these chars are invisible in all editors and terminals but are processed by LLM tokenizers, making them a covert injection channel. Document the new attack categories in dangerous-code-patterns.md and prompt-injection-patterns.md. Fix script path references in SKILL.md to use relative paths instead of the removed CLAUDE_SKILL_ROOT variable, and update the skill discovery search order to prefer .agents/skills/ first. Updates agents.lock to commit 89a1f01 and aligns resolved_path entries with the canonical skills/ tree layout. Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 95f285d. Configure here.
Sorry, something went wrong.
| f"the prompt. Command: {cmd}", | ||
| "evidence": line.strip()[:200], | ||
| "category": "Pre-prompt Injection", | ||
| }) |
There was a problem hiding this comment.
Medium Severity
The !… pre-prompt regex scans all of `SKILL.md`, so documenting the attack syntax (e.g. the `!`command bullet on line 109) is reported as a high-severity “Pre-prompt Command” even though no shell runs at load time.
Additional Locations (1)Reviewed by Cursor Bugbot for commit 95f285d. Configure here.
Sorry, something went wrong.
| "description": f"{desc}. Bundled test files execute as a side effect of running " | ||
| "the test suite — review file contents for hidden payloads.", | ||
| "category": "Test File RCE", | ||
| }) |
There was a problem hiding this comment.
Low Severity
Test auto-discovery loops over every test_patterns entry without stopping after a match, so one Python file can match both test_*.py and *_test.py and emit two separate high-severity findings for the same path.
Reviewed by Cursor Bugbot for commit 95f285d. Configure here.
Sorry, something went wrong.
| parts = chunk_data.split(b"\x00", 4) | ||
| if len(parts) >= 5: | ||
| keyword = parts[0].decode("ascii", errors="ignore") | ||
| value = parts[4][:200].decode("utf-8", errors="ignore") |
There was a problem hiding this comment.
Medium Severity
iTXt chunks are parsed by splitting on null bytes only, but the PNG spec places one-byte compression flag and method between fields without null separators, so parts[4] often is not the text payload and metadata findings can be wrong or missed.
Reviewed by Cursor Bugbot for commit 95f285d. Configure here.
Sorry, something went wrong.
| elif chunk_type == b"iTXt": | ||
| # iTXt: keyword\0comprFlag\0comprMethod\0langTag\0transKeyword\0text | ||
| parts = chunk_data.split(b"\x00", 4) | ||
| if len(parts) >= 5: | ||
| keyword = parts[0].decode("ascii", errors="ignore") | ||
| value = parts[4][:200].decode("utf-8", errors="ignore") |
There was a problem hiding this comment.
Bug: The code incorrectly parses PNG iTXt chunks by splitting on null bytes. It misinterprets the fixed-size comprFlag and comprMethod fields as null-terminated, leading to incorrect metadata extraction.
Severity: HIGH
The fix requires parsing the iTXt chunk according to its specification instead of relying on split. First, find the keyword by splitting on the first null byte. Then, read the next two bytes directly for comprFlag and comprMethod. The remaining data can then be split on the remaining null bytes to correctly extract the language tag, translated keyword, and the final text content.
Prompt for AI AgentReview the code at the location below. A potential bug has been identified by an AI agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not valid. Location: .agents/skills/skill-scanner/scripts/scan_skill.py#L496-L501 Potential issue: The PNG `iTXt` chunk parser at `scan_skill.py:496` incorrectly assumes all fields are null-terminated. The PNG specification defines `comprFlag` and `comprMethod` as single-byte binary fields, not null-terminated strings. The current implementation uses `chunk_data.split(b"\x00", 4)`, which fails for uncompressed chunks (the common case) where `comprFlag` is `0x00`. This creates an extra empty part in the split result, causing the code to incorrectly identify the translated keyword as the text content and miss the actual text. Consequently, the scanner will fail to detect malicious text in the most common type of PNG text metadata.
Did we get this right? 👍 / 👎 to inform future reviews.
Sorry, something went wrong.
| @@ -441,7 +599,10 @@ def scan_skill(skill_dir: Path) -> dict[str, Any]: | |||
|
|
|||
| all_findings.extend(script_findings) | |||
|
|
|||
There was a problem hiding this comment.
Unhandled OSError in symlink section can abort the entire scan
If path.readlink() or path.resolve() raises an OSError (e.g. a permission-denied error on a symlink in a restricted directory), the exception propagates unhandled through this call and crashes scan_skill, returning no findings at all. Wrap the symlink loop body in a try/except OSError like the PNG and package.json sections already do.
EvidenceIdentified by Warden code-review · 342-AW8
Sorry, something went wrong.
| @@ -441,7 +599,10 @@ def scan_skill(skill_dir: Path) -> dict[str, Any]: | |||
|
|
|||
| all_findings.extend(script_findings) | |||
|
|
|||
There was a problem hiding this comment.
rglob("*") in check_structural_attacks() follows directory symlinks on Python <3.13, enabling filesystem-traversal DoS against the scanner
check_structural_attacks() enumerates the skill directory with skill_dir.rglob("*") (symlink scan, test-file scan) and skill_dir.rglob("*.png") (PNG scan) without disabling symlink following. On Python 3.9–3.12 (the script declares requires-python = ">=3.9"), pathlib.Path.rglob descends into directory symlinks, so a malicious skill containing a single directory symlink to / (or ~) makes the scanner enumerate and, for the PNG branch, read arbitrary files across the whole filesystem — the very class of attack the symlink check was added to catch. A circular symlink can additionally trigger runaway recursion/resource exhaustion. The is_symlink() guard at the top of the loop only fires after rglob has already begun descending into the symlinked subtree, so it does not prevent the traversal.
EvidenceIdentified by Warden find-bugs · ZTP-EUB
Sorry, something went wrong.
Codecov Results 📊✅ 89905 passed | ⏭️ 6240 skipped | Total: 96145 | Pass Rate: 93.51% | Execution Time: 325m 26s 📊 Comparison with Base Branch
✨ No test changes detected All tests are passing successfully. ✅ Patch coverage is 100.00%. Project has 2402 uncovered lines. @@ Coverage Diff @@
## main #PR +/-##
==========================================
- Coverage 89.93% 89.90% -0.03%
==========================================
Files 192 192 —
Lines 23784 23784 —
Branches 8210 8210 —
==========================================
+ Hits 21389 21382 -7
- Misses 2395 2402 +7
- Partials 1342 1342 —Generated by Codecov Action |
Sorry, something went wrong.
Update the agent lockfiles to the latest and greatest
| Back | FazBrowse Home | New Git URL |
Update the agent lockfiles to the latest and greatest