diff --git a/CHANGELOG.md b/CHANGELOG.md index 564cb5e8..0f58b090 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +### 2.5.3 (Tuesday, August 04, 2026) +### Features/Bug Fixes +* fix(analyzers): share Python AST parsing for environment-read detection (#332) +* fix(output-handling): avoid RegExp.exec false positives (#341) +* docs(skill): allow delegated import MR preparation +* docs(lifecycle): optimize OSS import queue and cutoff +--- ### 2.5.2 (Tuesday, August 04, 2026) ### Features/Bug Fixes * test(mp2): lock the layout-span guard against regressions (#342) diff --git a/docs/release/skillspector-2.5.3.md b/docs/release/skillspector-2.5.3.md new file mode 100644 index 00000000..4eb7f659 --- /dev/null +++ b/docs/release/skillspector-2.5.3.md @@ -0,0 +1,51 @@ +# SkillSpector v2.5.3 + +Released: 2026-08-04 + +## Summary + +This patch release improves static-analysis accuracy and consistency. It reduces false positives for JavaScript and TypeScript regular-expression execution patterns and shares Python AST parsing across related analyzer steps. + +## Highlights + +- Avoid false positives from JavaScript and TypeScript `RegExp.exec` calls in output-handling analysis. +- Reuse parsed Python ASTs across analyzer steps for more consistent environment-read detection. + +## Added + +- Shared Python AST parsing infrastructure for analyzer steps that inspect the same source file. + +## Changed + +- Environment-read detection and related static analysis now reuse parsed Python source information where available. + +## Fixed + +- Do not classify JavaScript and TypeScript regular-expression `exec` calls as unsafe output handling. + +## Security + +- None. + +## Breaking Changes and Migration + +- None. + +## Deprecations + +- None. + +## Validation + +- `git diff --check c4eaaa467f192e46258aa615dc5447e3647e7fa6...HEAD` — passed for each imported PR. +- CI validation for imported GitHub PRs [#341](https://github.com/NVIDIA/SkillSpector/pull/341) and [#332](https://github.com/NVIDIA/SkillSpector/pull/332) — passed. + +## Known Limitations + +- None. + +## References + +- [GitHub PR #341](https://github.com/NVIDIA/SkillSpector/pull/341) +- [GitHub PR #332](https://github.com/NVIDIA/SkillSpector/pull/332) +- `CHANGELOG.md` diff --git a/pyproject.toml b/pyproject.toml index 8d5c0a8d..ab464560 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "skillspector" -version = "2.5.2" +version = "2.5.3" description = "SkillSpector: Security scanner for AI agent skills (Claude Code, Cursor, and similar). Scans skills for vulnerabilities, malicious patterns, and security risks before installation. Supports Git repos, URLs, zips, and local directories; runs static pattern checks and optional LLM semantic analysis; outputs terminal, JSON, and Markdown reports with risk scoring." readme = "README.md" license = "Apache-2.0" diff --git a/src/skillspector/input_handler.py b/src/skillspector/input_handler.py index b93712c2..125e6d92 100644 --- a/src/skillspector/input_handler.py +++ b/src/skillspector/input_handler.py @@ -176,7 +176,7 @@ def _get_temp_dir(self) -> Path: def _is_git_url(self, path: str) -> bool: """Check if path is a Git repository URL.""" - if not path.startswith(("http://", "https://", "git@")): + if not path.startswith(("https://", "git@")): return False parsed = urlparse(path) host = parsed.hostname or "" @@ -190,7 +190,7 @@ def _is_git_url(self, path: str) -> bool: def _is_file_url(self, path: str) -> bool: """Check if path is a direct file URL.""" - if not path.startswith(("http://", "https://")): + if not path.startswith("https://"): return False return not self._is_git_url(path) diff --git a/tests/unit/test_input_handler.py b/tests/unit/test_input_handler.py index f90507f6..e3c7301f 100644 --- a/tests/unit/test_input_handler.py +++ b/tests/unit/test_input_handler.py @@ -102,6 +102,13 @@ def test_scp_url_is_git_url() -> None: assert InputHandler()._is_git_url("git@github.com:org/repo.git") is True +def test_http_urls_are_not_accepted_as_remote_inputs() -> None: + """Network inputs require HTTPS unless they use SSH's scp-style syntax.""" + handler = InputHandler() + assert handler._is_git_url("http://github.com/org/repo.git") is False + assert handler._is_file_url("http://raw.githubusercontent.com/org/repo/SKILL.md") is False + + def test_validate_url_host_scp_extracts_github() -> None: """_validate_url_host extracts 'github.com' from an scp-style URL.""" host = InputHandler()._validate_url_host("git@github.com:org/repo.git", ALLOWED_GIT_HOSTS) diff --git a/uv.lock b/uv.lock index 72d53ae8..8e2c47c9 100644 --- a/uv.lock +++ b/uv.lock @@ -2675,7 +2675,7 @@ wheels = [ [[package]] name = "skillspector" -version = "2.5.2" +version = "2.5.3" source = { editable = "." } dependencies = [ { name = "boto3" },