Skip to content

Prepare SkillSpector 2.13.3 maintenance release - #958

Merged
yashrajp22 merged 36 commits into
yashraj/v2.13.0-basefrom
yashraj/release-2.13.3
Nov 2, 2026
Merged

yashrajp22 merged 36 commits into
yashraj/v2.13.0-basefrom
yashraj/release-2.13.3

Conversation

@yashrajp22

@yashrajp22 yashrajp22 commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Prepare 2.13.3 on top of published v2.13.2. This candidate retains the original large-review, response-validation, and parser-ownership changes and adds 15 important P0 fixes already merged upstream, plus the required merged MCP pin-ownership dependency. Selection focuses on security coverage, verdict correctness, scan integrity, input preservation, and dependency security.

Current correction and validation — 6fd523afd26a8b0099f9ea465f4b9e157cdf044d

AISOP-only directories could use a skill input as the report/baseline destination and overwrite it. The shared preflight now checks file identity against the primary Markdown input and every eligible AISOP candidate without parsing their contents. It covers malformed/oversized and multiple bundles, hardlinks, symlinks and parent-directory aliases. Recursive checks include hidden children and secondary bundles before scan limits can omit a child. Incomplete discovery refuses an existing output; a new destination or stdout keeps the existing explicit partial-scan behavior.

Current correction check Result
Focused regression selection 680 unique passes / 4 skips per source and installed-wheel mode, including 48 new cases. Seven modules run on Python 3.13; the Git-dependent input-handler module runs on the prepared Python 3.12 runtime. Ruff lint/format and Git whitespace checks pass.
Full CLI preservation and output controls 66 checks pass: 56 early rejections with zero graph/provider work and 10 allowed-output controls. All source bytes and file identities are preserved; 33 source/wheel pairs agree. Before-fix overwrite reproductions are retained.
Real-skill offline comparison 24 scans across 12 full directories preserve the preceding 3417998a candidate's findings, suppression, risk and completeness. Only random finding IDs are normalized.
Genuine AI validation 10 final scans, 182 actual provider requests, 990,693 known tokens; no provider or response-validation errors. All six representative real-skill scans complete all five AI stages. Four AISOP scan/baseline controls complete all four applicable AI stages; TP4 is correctly not applicable without a Markdown manifest. Inputs remain unchanged.
Live baseline comparison Another 10 scans / 182 actual requests / 991,147 known tokens at 3417998a. These are separate from the final-candidate totals.
Package and commit identity Fresh wheel SHA-256 a421dffba5e0f966bf1baf8acd77f4750a8ece0afc5520ecf49252b4004a8577; all 126 package files match the committed application. Runtime checks execute 57c8a9ff; final 6fd523af changes only test formatting and four diagnostic expectations. Application, build, configuration and dependency bytes are identical; the affected eight test cases pass again in both modes on final test files.
Current hosted CI All six checks pass for 6fd523af in run 41390190517, including full unit/coverage, completed 2026-11-02 06:29 UTC.

Independent review and real CLI reproductions close the original AISOP overwrite finding, Greptile's hidden-child finding on intermediate 6a22c882, and the subsequently identified incomplete-discovery path. Greptile did not review the final head; CodeRabbit remained unavailable. No final-head external clean-review claim is made.

Initial evidence remains recorded: the first Python 3.13 image lacked Git, so its one affected existing module was verified in the prepared Python 3.12 environment; four existing recursive-alias assertions expected the old diagnostic and were updated to the intentional fail-closed message, retaining exit, input-preservation and no-scan assertions. The initial AISOP live expectation was corrected to account for legitimately inapplicable TP4; no provider run was repeated to obtain a cleaner result. Parallel verification groups used at most three containers, and skill payloads were never executed.

This fixes output preservation. Existing missing-reference reports, the deferred 9/10 generated-helper inspection and the historical provider limitations below remain. The release owner authorized publication after CI completion on 2026-11-02. All six current-head checks have passed; the publication hold is lifted.

Python string completion correction (3417998a6bc6768f0759f938bae5b1bd29a1dc7e)

The second large input regressed to 108/109 statically completed files because a diagnostic string included a checkout-folder name derived entirely from a fixed URL. The scanner treated this known value as unknown and introduced an artificial parsing ambiguity. It now resolves a bounded set of constant-only string operations and substitutes only a proven complete field containing a plain filename component. Unknown values, changed bindings, escaped helpers, bundled standard-library replacements, class-local lookup, and nested/converted/formatted fields retain conservative handling. Reaching the source inspection bound still reports incomplete inspection even when replacing known fields shortens the projected text. Uploaded code is never executed.

Historical validation of 3417998a (before the AISOP output-guard correction):

Check Result
Original 118-batch large input 109/109 statically inspected files in source and fresh installed wheel; all five AI stages and all 118 actual TP4 batches complete in 267.614s / 280.728s. All 98 original static findings are retained. Its three existing missing-reference reports remain.
Original 145-batch workload All five AI stages and all 145 actual AI batches complete in 226.141s / 229.424s; static inspection remains 62/62. Existing missing/unresolved references remain.
Focused Python 3.13 tests 507 passed from source and 507 from the installed wheel; Ruff lint and formatting pass.
Python 3.12 available test selection 13,301 passed, 23 skipped, 137 deselected, 4 expected failures in each mode. Source took 684.06s; wheel took 697.31s. The local YARA-test omission is disclosed below.
Offline CLI comparison 86 scans across 43 directories, with exact source/wheel findings and completeness parity. All 78 comparisons against the preceding 3986a294 candidate retain every finding after normalizing only random finding IDs. CAD's 108/109 → 109/109 improvement is the sole completeness change.
Genuine live CLI matrix 40 scans: 20 source and 20 installed wheel. All 28 real-skill scans complete all five AI analyzers. Overall, 34/40 complete all AI work; the six intentionally hostile controls with provider refusals are disclosed below.
Cutoff and neighboring controls All ten quick full-directory checks meet their expected complete/incomplete outcomes. Eight cutoff regressions demonstrably fail on the earlier implementation and pass after correction; three shorter controls remain complete.
Package identity Fresh wheel SHA-256 c60859cce59b9b46ea39b5fc2452c644dd345fdcd4ac3cbd24a9202bcf994d2e; all 126 package files match the committed source. Independent checks verify the source/package identities and result records.
Hosted CI All six checks passed for 3417998a in CI run 41232971004. This is historical evidence; current-head CI is listed above.

Live tests used actual model responses through the configured gateway and ran in parallel with at most three containers. The 40 final-head scans made 2,750 genuine AI requests, with 15,673,014 known tokens, no HTTP errors, no missing usage, and no interrupted runs. The 33 structured-response validation-error attempts comprise 20 recovered attempts and 13 terminal provider refusals. Those 13 refused work items appear as 12 public exception records because one record combines two analyzers; they are not successful recoveries or proof of malformed JSON.

The six refused scans are source/wheel runs of the real-command browser control and the two long-string cutoff controls. They retain explicit incomplete AI review and the intended static limits. They were not rerun to obtain clean outcomes. Fourteen successful OSV requests are counted separately; online dependency results replace the unavailable-OSV fallback warning from offline scans. Live AI review can add annotations and findings, while the offline comparison establishes unchanged static findings.

Independent review and Greptile identified class-default/comprehension scope, warning-filter, and shortened-projection cutoff edge cases. All three findings are addressed and independently checked against the final source and regression evidence. Greptile reviewed preceding correction heads, so this is not a claim of a clean Greptile run on the final head. CodeRabbit's review service remained unavailable and is not counted as passing.

Initial test-oracle/fixture-construction failures and earlier interrupted live runs are retained separately. The interrupted runs' provider usage remains unknown; they are excluded from the final-head totals. The fresh preceding-candidate CAD baseline scans are also separate from these 40 scans.

Remaining limits and publication status

  • The generated-helper/archive workflow remains 9/10 statically inspected, as previously deferred. Existing reference caveats remain separate from successful AI completion; this does not establish blanket signing readiness.
  • One unrelated YARA test file is missing following a host-security quarantine event and is omitted from local exports. No protection was bypassed, the deletion is excluded from commits, and package code is complete. The local broad tests are an available selection; full-repository hosted CI has now passed for the current head.
  • The AISOP output-overwrite finding is addressed by the current correction and validation above. Current-head CI and the release owner's publication approval are now complete.
  • Publication authorized on 2026-11-02 after current-head CI passed. Earlier-head results and hold statements below are historical. Naren's earlier change-request review remains recorded against 3417998a; the subsequent overwrite correction and validation are documented above.

Original candidate changes retained

  • #945: SKILLSPECTOR_TP4_MAX_BATCHES defaults to 256; SKILLSPECTOR_MAX_WORKFLOW_SECONDS defaults to 1080 seconds (18 minutes).
  • #946: completed-response validation, bounded formatting recovery, shared response settings, and asynchronous semantic discovery.
  • #948: bounded shell, Python-string, and browser-template ownership fixes. Ambiguous execution remains explicitly incomplete.
  • Required upstream dependency 9919c159: run TP4 batches concurrently through the existing shared concurrency limiter. This dependency was present in the source PRs' main-branch context.
  • Review fixes: require binding proof when JavaScript undefined is shadowed; keep formatting-recovery transport failures within the shared retry/deadline budget. Regression checks cover known/unknown bindings, connection errors, rate limits, server errors, invalid formatting output, and exhausted budgets.

Important merged P0 PRs added

PR Release impact
#765 Inspect Pipenv dependencies and locked versions; retain explicit coverage limits.
#772 Include gap-fill findings in batch risk scores, recommendations, and exit status.
#776 Inspect npx package commands in JSON MCP configurations.
#826 Trace nested urllib request-header credentials to network sinks.
#860 Add bounded multiline ransomware detection while retaining existing stronger signatures.
#874 Restore PowerShell SC3 obfuscation and P2 hidden-instruction coverage.
#881 Recognize additional MCP client credential/configuration filenames.
#882 Preserve shell-line boundaries across Markdown fences during marker reconstruction.
#893 Detect automatically run test carriers writing agent-memory files, including raw Windows paths.
#906 Inspect extensionless Python scripts with CRLF shebangs.
#915 Refresh four advisory-affected dependency lockfile pins.
#919 Keep unavailable requested custom YARA rules explicitly incomplete.
#924 Prevent baseline output from overwriting primary inputs and aliases.
#938 Prevent recursive reports from overwriting discovered child inputs.
#949 Continue inspecting later artifacts after a local matcher timeout.

Dependencies and backport scope

Spectorian review corrections (3986a294c511be12cb6701ba698ea4ddd2ff837d)

Addressed both items in Spectorian's review comment:

  • P1 — fence reconstruction: reject invalid line prefixes before walking a backtick run, pass the caller's exclusive end bound into fence checks, and keep truncated lines conservative. New regressions enforce a linear character-read ceiling for 1 KiB, 4 KiB, and 16 KiB rejected backtick runs and exercise four clipped end bounds.
  • P3 — JSON finding locations: use JSON-decoded key tokens and retain source member order alongside last-key-wins object values. Escaped command keys, duplicate command/server keys, and duplicate arguments now retain the correct winning command's source line.

Validation of prior review fixes (3986a294c511be12cb6701ba698ea4ddd2ff837d)

Check Result
New regression cases 10 fence-scaling/bound cases and 7 escaped/duplicate JSON-key location cases failed before their fixes and pass afterwards.
Focused source suites 1,825 passed across reconstruction, Python string ownership, static parse limits, host-language shell ownership, shell quote ownership, multiline prompt spacing, and both MCP rug-pull modules.
Fresh installed wheel 50 passed: both MCP modules (40 tests) and the 10 new fence regressions, using fresh test copies outside the checkout with imports verified from installed site-packages.
Independent review No actionable issue introduced by these corrections was identified.
Lint and formatting Ruff lint, Ruff formatting, and git diff --check pass.
Packaging Wheel/sdist build, strict Twine, 125 package-file integrity checks, 129 RECORD hashes, all 127 frozen dependency pins, and dependency compatibility checks pass. Prior candidate artifacts are retained separately.
Hosted CI for this head All six checks passed in CI run 41205246622, completed 2026-10-31 15:06:02 UTC: unit/coverage, lint, Docker smoke, OpenCode TypeScript tests, DCO, and changes. The run records head 3986a294c511be12cb6701ba698ea4ddd2ff837d; the pull-request workflow tests its merge with the release base.
Full hosted unit/coverage suite 13,383 passed, 23 skipped, 4 expected failures, 137 deselected; 90% total coverage on Linux/Python 3.12.13 in 6,193.42 seconds (1h 43m 13s). Command: pytest -m "not integration and not provider" --cov=src/skillspector --cov-report=term-missing --cov-report=xml tests/. The six warnings were three existing unknown pytest.mark.timeout warnings and three duplicate-ZIP fixture warnings; no test failed.

The completed run above validates the prior review-fix head 3986a294c511be12cb6701ba698ea4ddd2ff837d in the hosted pull-request workflow. The df3d072c result below remains historical evidence for the prior candidate. Live acceptance has not been rerun for this head; the historical 41ac82c live matrix and its acceptance limitations still apply as historical records. The documented local macOS worker-startup failures remain unresolved locally; hosted Linux success does not isolate their cause. No worker code or startup timeout was changed. Publication remains on hold.

Validation of prior expanded candidate df3d072cdf3e3410e6916c0642e06540d41dc5d1

All six hosted checks passed for this exact head, including the full Linux Python 3.12 unit/coverage run.

Check Result
Independent integration review Completed. Corrected overlapping memory-destination regex alternatives in #893 and the #938 maintenance CLI integration differences.
Source node/analyzer selection 9,304 passed, 4 expected failures. This selection ran at e855b1be; its analyzer code is unchanged in the final CLI-only correction.
Final source CLI and multi-skill selection 443 passed, including all 14 recursive output cases that initially exposed the maintenance differences. Both existing skill-count bounds are tested without adding the unshipped --max-skills option.
Fresh installed wheel 443 CLI/multi-skill tests passed against the rebuilt final wheel. An additional 1,412 analyzer tests passed against the preceding wheel; all analyzer code and dependency pins are unchanged.
Original 41ac82c comparison 13,164 passed, 14 skipped, 4 expected failures, 137 deselected.
Lint and formatting Ruff lint, Ruff formatting, and git diff --check pass.
Packaging Final wheel and sdist build and strict Twine checks pass; all 125 package files match source, sdist, wheel, and installation; 129 RECORD hashes verified; all 127 frozen dependencies match and compatibility checks pass.
Hosted final-head CI All six checks passed: unit/coverage, lint/formatting, Docker smoke, DCO, OpenCode TypeScript tests, and change detection. CI run 41118624360 completed successfully for df3d072cdf3e3410e6916c0642e06540d41dc5d1.
Final hosted Linux unit/coverage suite 13,366 passed, 23 skipped, 4 expected failures, 137 deselected; 6 warnings. Reported total coverage: 90%. The test step completed on October 30, 2026, at 2:35 PM PDT (21:35 UTC), with pytest duration 1h42m56s.

The three new isolated Python/JavaScript/TypeScript regex timeout regressions failed before the #893 review correction and pass afterwards; all 40 MP3 memory-write tests pass, including Windows paths. The 14 recursive guard cases likewise failed before the CLI correction and pass afterwards.

Local validation limitation: the broad final macOS remainder run was interrupted after four unchanged multiprocessing tests exceeded their 20-second worker-startup bounds. Focused candidate reproductions hit the same bound; an additional credential/tracing-isolated diagnostic remained incomplete and was stopped. The host had approximately 16.4 GiB of 17 GiB swap in use. The original baseline and earlier expanded-candidate run passed the same worker controls. A baseline control under the later host conditions also passed, but took 117.80s versus 14.247s in the original full run; this shows slowdown without reproducing the candidate's timeout or isolating its exact cause. No worker code or test timeout was changed. These local candidate runs remain failed/incomplete and are not counted as a clean full-suite pass. The independent hosted Linux suite above passed for the final head; the local macOS limitation remains documented.

Live acceptance has not been rerun for this expanded candidate. The previous matrix below applies to 41ac82c only. Its acceptance limitations must not be described as resolved.

Historical validation and acceptance limitations — original candidate 41ac82c

Validation of candidate 41ac82c62929c9e6429d9499bfe191bf75979da8

Source and freshly built, installed packages were tested in isolated Linux containers. Independent review checked the source/package identities and result records. Live tests used actual responses from azure/anthropic/claude-opus-5 through the configured OpenAI-compatible gateway; affected skill payloads were inspected, not executed. Independent test groups ran in parallel, with at most three containers. The completed matrix contains 76 full-CLI live scans (72 candidate, 4 baseline; 38 source, 38 wheel) and 4,538 genuine provider calls. Timeout requests with unknown usage remain recorded. Deliberate negative controls are expected to return incomplete results.

Check Result
Python 3.12 unit selection 13,155 passed for source and separately for the installed wheel; 23 skipped, 4 expected failures, 137 deselected in each. Source initially had 14 environment-only failures; all passed after correcting the container's writable uv cache, without source/test changes.
Python 3.13 focused regression selection 590 passed for source and 590 for the wheel.
Offline CLI comparison 39 skills, source and wheel: 78 candidate scans compared with 78 retained baseline scans. Results agree between source/package; existing non-coverage security findings are preserved.
Packaging Strict package checks pass; rebuilding the source distribution produces the identical wheel.
Ordinary live CLI matrix 42 runs: 28 candidate runs across 14 real skill directories, 12 candidate synthetic runs, and 2 baseline large-skill runs. All five AI checks completed in 35/40 candidate runs; exceptions are disclosed below.
Live parser/batch/binding controls 12 full-CLI scans meet their expected complete or incomplete outcomes and preserve raw security findings.
Controlled live response faults 18 full-CLI scans: 10 lossless-formatting cases pass; 8 changed-content, truncated, refused, or missing-required-field cases remain explicitly incomplete. These faults were deliberately applied to genuine provider responses and are separate from naturally occurring failures.
Short workflow deadline Source and wheel return explicit runtime-incomplete results with a 3-second workflow budget. Whole CLI duration, including startup/cleanup, was about 12 seconds.
Default 256/257 boundary Fresh wheel: 256 actual AI batches complete in 3m12s. A 257-batch input completes 256 in 3m05s and reports the remaining batch as incomplete with output_limit. The batch-limit environment variable is unset in both runs, so these exercise the default.

The retained 145-batch workload completed every AI batch in 6m28s from source / 4m46s from the wheel. The v2.13.2 comparison stopped at 74 completed batches at its 10-minute workflow deadline. The retained 118-batch second large input completed every AI batch in 5m11s / 5m58s; baseline stopped at 59 batches. These compare the combined releases with their defaults, not an isolated single-change benchmark. Existing missing-reference incompleteness remains.

Acceptance limitations

  • The second large input has a new static-completion regression: 108/109 files complete versus 109/109 on v2.13.2. A harmless diagnostic string is conservatively treated as ambiguous; all 98 offline findings are retained. Its AI runtime improvement does not establish complete static inspection or signing readiness.
  • One real-skill wheel run remained incomplete: a review of one document exhausted four attempts with required response fields missing. The source run completed. This genuine failure is retained; the sample was not rerun to obtain a clean result.
  • Four deliberately dangerous synthetic runs encountered genuine provider refusals and remained visibly incomplete. All 145 TP4 batches still finished in each late-batch mismatch case and the final injected mismatch was found.
  • The generated-helper/archive workflow remains 9/10 statically inspected; support for its remaining generated and loaded commands is deferred. This candidate does not fully resolve that workflow.
  • The tested route requests tool responses without strict: true. These results do not establish native schema enforcement or eliminate malformed/missing-field responses across providers.
  • Pi/OpenCode wrappers retain their 120-second timeout. Use the CLI for larger scans. Testing covers the recorded Linux/Python/provider combinations, not every platform, model, or possible input.

Greptile reported no new actionable findings after the two review fixes. CodeRabbit could not connect to its review service and is not counted as a passing review. GitHub lint, DCO, TypeScript tests, Docker smoke, and change detection pass; the unit/coverage job is still running.

Publication authorized on 2026-11-02 after all current-head checks passed. Publish 2.13.3 through the existing maintenance-branch release workflow. The disclosed remaining limitations still apply; broader PowerShell/JavaScript/Markdown parser support is planned for 2.13.4.

yashrajp22 and others added 14 commits October 30, 2026 22:35
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
(cherry picked from commit 4e5777d)
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
#946)

Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Adapt upstream commit 9919c15 and align the additional response-validation tests with the asynchronous path.

Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
…lidation

Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Update anyio, certifi, urllib3 and langgraph-sdk to the fixed versions
listed in #910. Keep all other package entries unchanged.

Signed-off-by: Deepak Jain <deepujain@gmail.com>
(cherry picked from commit 914116b)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
(cherry picked from commit 85a236d)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
* fix: preserve baseline input files when selecting output

Signed-off-by: Christopher Kevin <christopherk@nvidia.com>

* fix: validate baseline destinations for local remote-like names

Signed-off-by: Christopher Kevin <christopherk@nvidia.com>

---------

Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
(cherry picked from commit 6a0d099)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
…#906)

A shebang that names Python but ends in CRLF kept the carriage return in
the interpreter name, so the file was classified as non-Python and the
Python analyzers skipped it, though `python3 <script>` runs it unchanged.

Read the shebang with its CRLF ending taken as LF as one more view next to
the truncated Linux ones. When the views disagree the source is ambiguous
and analyzed fail-closed; it is still not definitively Python.

Signed-off-by: alteralto <182909819+alteralto@users.noreply.github.com>
(cherry picked from commit c7f7f3c)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
…into one marker directive (#882)

A fenced shell example such as `run <monitorId>` followed by `delete <monitorId>`
on the next line was scanned as an active, unresolvable marker directive and
marked the file partial with obfuscated_instruction_text. The three backticks
of a fence line opened a quote in _sentence_boundaries that swallowed every
line break up to the next fence, so both lines formed one clause.

A backtick run outside a quote is now skipped only when it is a real fence
line: three or more backticks at line start (up to three spaces of
indentation), followed by nothing or a bare language label. Every other run
(mid-line, after text, inline spans, prose after the run) keeps opening a
quote as before, so directives split by such a run still fail closed.

Refs #868

Signed-off-by: elliottwaves-20 <pail1217@web.de>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 5203c3f)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
…e and Roo Code (#881)

AS2 matched only mcp.json and mcp_config.json, so a skill that read the server list of Claude Desktop (claude_desktop_config.json), Claude Code (~/.claude.json), Cline (cline_mcp_settings.json) or Roo Code (mcp_settings.json) got no AS2 finding. The direct-access patterns now share one file-name pattern that covers these files.

Signed-off-by: Dmitry Sergeev <sergeevdms@gmail.com>
(cherry picked from commit 3ae98af)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
#514 typed .ps1 files as "powershell" instead of "other", but the SC3
and P2 file-type gates list "other" and not "powershell". A base64 stage
passed to IEX in a .ps1 script therefore produced no finding, while the
same bytes under an untyped extension produced SC3 HIGH.

Add "powershell" to both gates, as #615 did for "perl".

Signed-off-by: Udaya Tejas <udayatejas2004@gmail.com>
(cherry picked from commit d56c2f1)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
@rng1995
rng1995 marked this pull request as ready for review October 30, 2026 19:35
udsy19 and others added 11 commits October 30, 2026 12:36
`ransomware_behavior`'s `$walk_encrypt` and `$mass_overwrite` have no
dot-all flag, so they only match when `os.walk(` shares a line with the
`.encrypt(` or `open(..., "wb")` call. Ordinary ransomware code puts the
walk, the read, the encryption and the write-back on separate lines.
Without a ransom note nothing in the rule fires, and a skill whose script
encrypts every file under the home directory in place scores SAFE.

Add a separate `ransomware_behavior_multiline` rule at HIGH / 0.6. It
requires `os.walk(`, an `.encrypt(`/`.cipher(` call and a binary-write
`open()` within 1 KiB of the same walk. A signature cannot prove that the
write replaces the walked file, so this rule reports at reduced
confidence, the same way `reverse_shell_multiline` does. It stays quiet
when `ransomware_behavior` already matches, and that rule is unchanged.

Signed-off-by: Udaya Tejas <udayatejas2004@gmail.com>
(cherry picked from commit 3ca7def)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Signed-off-by: Efe <efe@rexcode.co.uk>
(cherry picked from commit 492955f)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
The npx, uvx and pip checks searched the rest of the line for anything
that looked like a version pin, so an unrelated argument, a URL with a
port, or a neighboring pinned command suppressed the finding for an
unpinned package (for example `npx evil-package --label helper@1.2.3`
or `npx @scope/mcp-server http://localhost:3000/sse`).

Only the text attached to the package token now counts as its pin.

Signed-off-by: Sammy Tourani <sammytourani@gmail.com>
(cherry picked from commit 318bfdd)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
* fix(mcp-rug-pull): scan configured npx commands

Signed-off-by: Efe <efe@rexcode.co.uk>

* fix(mcp-rug-pull): locate each server command

Signed-off-by: Efe Gökdemir <gokdemirefe1903@gmail.com>

---------

Signed-off-by: Efe <efe@rexcode.co.uk>
Signed-off-by: Efe Gökdemir <gokdemirefe1903@gmail.com>
(cherry picked from commit 2b85712)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
* fix(supply-chain): parse Pipenv dependency manifests

Parse Pipfile TOML and Pipfile.lock JSON dependencies, reuse exact lock versions, and report incomplete dependency parsing. Add regression and CLI coverage.

Signed-off-by: YMuskrat <101849520+YMuskrat@users.noreply.github.com>

* fix(supply-chain): retain findings after Pipenv parser errors

Catch ValueError from Pipenv JSON/TOML parsing, including oversized integer conversion failures, and record a nonfatal dependency_parse_error for the offending file.

Add four regressions covering 5,000-digit metadata integers in both formats and CLI scans that retain unrelated SC2 and SC4 findings. Restore the interpreter digit limit after each case.

Signed-off-by: YMuskrat <101849520+YMuskrat@users.noreply.github.com>

* fix(supply-chain): keep locked versions with their project

Scope Python lock lookups to the manifest directory and keep Pipenv locks separate from other manifest types. Leave conflicting locked versions unresolved while still checking each locked entry. Addresses the project association review on #765.

Signed-off-by: YMuskrat <101849520+YMuskrat@users.noreply.github.com>

* test(supply-chain): isolate dependency versions across projects

Add 23 cases covering the exact docs Pipenv/root requirements layout, independent Pipenv projects, both component orders, unrelated same-directory manifests, conflicting categories, uv/Poetry scope and aggregate limits.

Validation: 662 focused tests, 10,027 unit tests and 124 integration tests passed, plus lint and formatting. All 23 new cases passed against a freshly built wheel using deterministic OSV responses.

Signed-off-by: YMuskrat <101849520+YMuskrat@users.noreply.github.com>

* fix(supply-chain): continue after file-local lockfile limitations

Keep collecting independent project lockfiles after Pipenv parse errors, unsupported sources and file-local limits. Stop only for the aggregate file, runtime or package budget.

Signed-off-by: YMuskrat <101849520+YMuskrat@users.noreply.github.com>

* test(supply-chain): retain resolution after partial Pipenv locks

Cover unsupported Git dependencies, malformed lockfiles, oversized entries and file-local entry limits in both file orders. Verify unrelated manifests still receive their locked versions and existing parse limitations remain reported.

Validation: 672 focused tests passed; all ten new cases passed against source and a freshly installed wheel. Unit tests passed after retrying 40 environment failures with the missing SOCKS dependency installed; 124 integration tests passed.

Signed-off-by: YMuskrat <101849520+YMuskrat@users.noreply.github.com>

---------

Signed-off-by: YMuskrat <101849520+YMuskrat@users.noreply.github.com>
(cherry picked from commit 1feb2c8)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
* feat(analyzer): score writes to agent-memory files as MP3 memory manipulation

MP1/MP3 prose patterns score the injection text, not the write, so a test
hook appending to MEMORY.md scored 0/100 SAFE (issue #879). This adds a
write-operation variant to the memory-poisoning analyzer: a write sink whose
destination resolves to a known agent-memory file (MEMORY.md, CLAUDE.md,
AGENTS.md, SOUL.md) or directory (.claude/, .cursor/, .agents/) is reported
as MP3 Memory Manipulation (HIGH), whatever the payload bytes are.

The carrier is scoped to files the developer toolchain auto-runs
(test_*.py, *_test.py, conftest.py, *.test.*, *.spec.*) so explicitly
invoked helpers, reads, and ordinary filenames stay quiet. Covers Python
(open/io.open with write mode, Path.write_text/write_bytes, shutil.copy*)
and TypeScript/JavaScript (writeFile(Sync)/appendFile(Sync) incl.
fs.promises, createWriteStream) sinks.

Verified against the five variants in #879: the inert canary rows go from
SAFE to CAUTION with a standalone MP3 finding, and the injection-payload
rows cross the 50 risk threshold (exit 1), while the prose-only control is
unchanged. Adds 34 unit tests; full unit suite and ruff are clean.

Signed-off-by: Varshith Puli <pulivarshit@gmail.com>

* fix(analyzers): preserve backslashes in raw-string memory destinations

Raw and rf Python string prefixes keep backslashes literal, so decoding
escapes collapsed r"C:\Users\alice\MEMORY.md" to "C:UsersaliceMEMORY.md"
and the MP3 write signal never fired. Decode escapes only for non-raw
literals, using the sink regex prefix the code already captures, and add
raw, rf, and raw .claude directory Windows tests through the analyzer.

Signed-off-by: Varshith Puli <pulivarshit@gmail.com>

---------

Signed-off-by: Varshith Puli <pulivarshit@gmail.com>
(cherry picked from commit 2de9b38)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
(cherry picked from commit 6498f0e)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
* fix(batch): include gap-fill findings in risk assessment

Signed-off-by: Efe <efe@rexcode.co.uk>

* test(batch): preserve caution for incomplete scans

Signed-off-by: Efe <efe@rexcode.co.uk>

---------

Signed-off-by: Efe <efe@rexcode.co.uk>
Signed-off-by: Efe Gökdemir <gokdemirefe1903@gmail.com>
(cherry picked from commit fdce443)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
The multiline prompt matcher reported its per-pattern timeout as a terminal analyzer limit. One expensive artifact therefore caused every later artifact to be marked partial without inspection.

Classify resource limits by scope: contain the matcher's local timeout to the affected artifact, while keeping shared workflow deadlines and output limits scan-terminal. Add regressions proving later artifacts continue after a local timeout and remain blocked after a global deadline.

Full-suite comparison against the same origin/main revision:

Main: 15,533 passed, 583 failed, 20 skipped, 250 deselected, 4 xfailed.

Fix: 15,534 passed, 583 failed, 20 skipped, 250 deselected, 4 xfailed.

The failure set is unchanged; the branch adds one passing regression test.

(cherry picked from commit 9adb1a6)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
@rng1995

rng1995 commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

@yashrajp22 - I have updated the release to include important P0 PRs

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
@Spectorian

Copy link
Copy Markdown
Collaborator

2 comments:
P1 — security_reconstruction.py:1212

Please check the line prefix before scanning the backtick run and respect the caller’s end bound. Rejected runs are rescanned at alternate backticks, making reconstruction quadratic. A roughly 16 KB fixture takes 23.9s versus 0.35s on base; checking the prefix first restores 0.43s. Please fix before merge and add a scaling regression alongside the existing fence tests.

=-=-=-=-

P3 (minor follow-up) — mcp_rug_pull.py:224

Parsed keys and regex matches can drift. An escaped "\u0063ommand" key makes the next server’s RP1 finding point to line 1 instead of line 8; duplicate keys also shift locations. Please derive positions consistently with JSON parsing and add escaped/duplicate-key location tests.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>

@rng1995 rng1995 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[SkillSpector Review]

Value and readiness

Reviewed release head 3986a294c511be12cb6701ba698ea4ddd2ff837d. The selected backports, completed-response validation and bounded ownership changes have substantial value. All six current hosted checks pass, but the intended input-preservation fix still misses a supported primary-input form. That required correction and the explicit release-owner hold prevent approval.

Material findings

Required — src/skillspector/cli.py:359. For directory inputs, the guard resolves only _manifest_file, which checks SKILL.md and skill.md. A valid AISOP-only bundle therefore remains a directory and bypasses is_file()/samefile(). With baseline ./bundle --no-llm -o ./bundle/workflow.aisop.json, the new call at cli.py:3291 permits the primary JSON as output. baseline_path then excludes that file from cached candidates before structured-input extraction (nodes/build_context.py:2686-2690); a successful or nonfatal scan reaches dump_baseline, which atomically replaces the writable JSON (suppression.py:834). The recursive AISOP guards cover a different route. This is an incomplete intended preservation fix; the underlying exposure also exists in 2.13.2.

Resolve the supported primary through shared bounded primary resolution before baseline exclusion or scanning, retain identity checks for aliases, and add a valid single-directory AISOP regression with no SKILL.md. Assert early rejection and unchanged primary bytes, including a same-file alias where applicable.

Previously examined issues are addressed: #946's HTTP fixture now supplies non-TP4 requested tool calls; formatting transport errors share the original retry/deadline budget; shadowed JavaScript undefined requires binding proof; Spectorian's fence-scaling/end-bound and escaped/duplicate JSON-location findings have focused fixes and regression controls. The memory-regex and recursive-CLI maintenance corrections remain present. I found no further demonstrated required change in the reviewed release diff.

PIC tradeoffs

Keep the publication/merge hold until explicit release-owner approval. Separately assess the disclosed static-completion regression (108/109 files versus 109/109 on 2.13.2), historical incomplete real-skill wheel assessment, and deferred generated-helper/archive coverage. Live acceptance belongs to historical 41ac82c and has not been rerun for this expanded/current candidate. Current hosted Linux success does not resolve the documented later local macOS worker-startup failures. Larger batch/time defaults retain their other resource bounds; Pi/OpenCode still stop at 120 seconds.

Verification and gaps

Reviewed the complete 65-file release diff, pinned production/test context, prior completed assessments, source comparisons, both Spectorian comments and current hosted evidence. Confirmed the fifteen named P0 backports and MCP pin-ownership dependency are merged upstream; #946/#948 remain open and their release adaptations were assessed directly. Decoded YARA as data: only the new bounded multiline rule is added and existing signatures are preserved. Lockfile comparison changes only the four stated third-party versions plus SkillSpector's version; Python remains >=3.12,<3.15. Inspected parser/consumer ownership, adversarial bounds, source offsets, retry accounting, 256/257 limits, retained findings, aliases and completeness tests.

Independently read current CI run 41205246622: 13,383 passed, 23 skipped, 4 expected failures, 137 deselected; 90% coverage. Packaging and historical live matrices remain evidence as described by the author. The overwrite finding is established by the source route above; no runtime reproduction is claimed. No contributor code, snippets, imports, tests, builds, YARA rules or scanner invocations were executed.

Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>

@rng1995 rng1995 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[SkillSpector Review]

Value and readiness

Re-reviewed 3417998a6bc6768f0759f938bae5b1bd29a1dc7e, including the complete four-commit/six-file increment since 3986a294. The bounded constant-string correction addresses the previously disclosed diagnostic-string completion case, with substantial source/wheel and adversarial regression evidence. Current hosted metadata shows all six checks SUCCESS. The earlier primary-input overwrite finding remains open and still requires changes.

Material findings

Still required — src/skillspector/cli.py:359. The guard and _manifest_file are byte-identical to the reviewed revision. For an AISOP-only directory, the resolver finds neither SKILL.md nor skill.md, retains the directory and bypasses is_file()/samefile(). baseline ./bundle --no-llm -o ./bundle/workflow.aisop.json can therefore exclude its existing structured primary through baseline_path before scanning and replace it with baseline JSON afterward. The PR description explicitly confirms this separate blocker remains unresolved. Resolve the supported primary using shared bounded resolution before exclusion or scanning, preserve alias identity checks, and add a valid single-directory AISOP regression asserting early rejection and unchanged primary bytes. This remains an incomplete intended preservation fix; the exposure also exists in 2.13.2.

No additional required correction was demonstrated in the new increment. Read the complete constant evaluator and its integration: native literal values, immutable module bindings, restricted helper/string/URL operations, bounded output, nearest-scope checks, bundled-standard-library rejection and exact complete field spans. Unknown or altered bindings, escaped helpers, reflective operations and unsupported field contexts retain conservative handling. Original-source cutoff exhaustion remains incomplete even when substitution shortens the projection. Earlier response-validation, HTTP-fixture, undefined-binding, fence-bound, JSON-location, memory-regex and recursive-CLI corrections remain intact.

PIC tradeoffs

The release-owner publication/merge hold remains explicit. The author now reports the original CAD case at 109/109 statically inspected files with all 98 findings retained, plus final-head source/wheel live validation; the older 108/109 result is historical. Evaluate those new acceptance records separately from the still-open overwrite fix. Generated-helper/archive inspection remains 9/10, deliberate provider refusals remain incomplete, and local test exports omit the quarantined YARA test file. The increment contains no such test deletion, and current hosted full-repository CI passes.

Verification and gaps

Read the whole increment, current pinned source/tests, all prior marked findings, review discussion and updated validation claims. Verified class/default/comprehension scope controls, warning-filter preservation, exact Unicode/CRLF field offsets, changed/escaped/imported bindings, native-library shadowing, cancellation/output limits and shortened-projection cutoff regressions. The two input-guard files match prior saved blobs exactly. Current Actions evidence is separate from the description's stale pending-job wording: changes, lint, test-unit, OpenCode TypeScript Tests, DCO Check and docker-smoke all SUCCESS. Private live/package records remain author-supplied evidence; no rerun is claimed. No contributor code, snippets, tests, imports, builds, model calls or scanner invocations were executed.

Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
@yashrajp22

Copy link
Copy Markdown
Collaborator Author

@rng1995, the additional end-to-end validation for the PRs you added reproduced the AISOP input-overwrite blocker you also flagged in your earlier review.

Fixed in 6fd523af, in this same PR. scan and baseline now reject an existing report destination that is the same file as the primary Markdown input or any eligible AISOP input, including hardlink and symlink aliases. This happens before scanning or excluding the output, and does not depend on parsing the JSON or selecting a primary bundle. The same guard checks every recursively discovered child, including hidden children and secondary AISOP files. If bounded discovery cannot verify the destination, the command refuses an existing output and asks for a new path; new outputs and stdout retain the existing incomplete-scan reporting.

Verified with the fixed application and a fresh installed wheel:

  • 48 new regression cases; the focused selection passes 680 tests with 4 skips per mode across Python 3.12/3.13. Lint and formatting pass.
  • 66 full-CLI guard/output checks: 56 reject before any graph/provider work; 10 allowed-output controls retain their expected behavior. Input bytes and file identities are preserved. The overwrite cases were reproduced before the fix.
  • 24 full-skill scans across 12 directories preserve the preceding candidate's findings and inspection completeness.
  • 10 final live AI scans, using 182 genuine requests, complete every applicable AI stage without provider or response-validation errors. Another 10 live scans establish the baseline comparison. Existing missing-reference findings and deferred generated-helper coverage remain.

Runtime checks executed application commit 57c8a9ff; final head 6fd523af changes only test formatting and four expected diagnostics. All application, build and dependency bytes are identical, and the affected tests were rerun on the final test files. Initial test/environment failures remain recorded.

Five current-head CI checks pass; the full unit/coverage job is still running.

Publication remains on hold pending the release owner's approval.

@yashrajp22 yashrajp22 added the release:publish Marks an OSS release pull request for publication label Nov 2, 2026
@yashrajp22
yashrajp22 merged commit 38a1dfe into yashraj/v2.13.0-base Nov 2, 2026
6 checks passed
@yashrajp22
yashrajp22 deleted the yashraj/release-2.13.3 branch November 2, 2026 06:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:publish Marks an OSS release pull request for publication

Projects

None yet

Development

Successfully merging this pull request may close these issues.