Repository navigation
fix(static): preserve shell and browser template boundaries - #948
Conversation
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>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
… headers 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>
…cues Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
0be31f2 to
6ad5426
Compare
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>
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>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
rng1995
left a comment
There was a problem hiding this comment.
[SkillSpector Review]
Value and readiness
The ownership refinements address substantial shell/Python/browser false positives, and the added tests cover many executable counterexamples, source bounds and cancellation paths. One browser binding proof remains unsound at this head, so the PR needs a focused correction before approval.
Material findings
Required — src/skillspector/javascript_tokens.py:1137: ordinary() accepts the spelling undefined as a primitive before consulting its lexical binding. JavaScript permits a parameter or local constant to shadow that global. Adapt the existing browser fixture by wrapping its display assignment in function renderList(undefined) { ... }, replacing rows.map with undefined.map, and calling renderList(external). The map receiver is then caller-supplied and unproved, but the primitive branch bypasses the existing parameter/argument analysis. The template fields can receive ownership, and the final native-call dependency check also accepts ordinary(undefined), allowing the selected backticks to be masked where unknown consumers must retain incomplete inspection. This violates the same safety boundary as the existing fake/unknown receiver controls; raw security text remaining visible does not prove that inspection completed.
Route shadowable undefined through binding resolution, and add parameter/local-constant controls that distinguish a proven JSON receiver from an unknown receiver. The current #958 release branch already contains this correction and those controls; that does not fix this PR's pinned source. This is a source-level ownership/coverage finding, without a claim of an executed scan or combined SAFE verdict. No earlier GitHub review findings were present in the retrieved history.
PIC tradeoffs
The shell proof appropriately refuses unsupported heredoc delimiters, transformed child-command offsets, unresolved startup effects and unknown printf behavior. Conservative extra partial warnings from unsupported scopes are a reasonable cost. Browser qualification deliberately assumes ordinary imported protocols and built-ins; explicit local shadowing belongs inside the proof and must be checked. The author's remaining 9/10-file workflow acceptance gap is disclosed rather than silently completed.
Verification and gaps
Reviewed exact head d781e77828c8df4ea42ce7a4a9858d656dd75b8b: the complete twelve-file diff, all added/changed tests, pinned surrounding lexer/ownership/dispatch code, description, and available review/comment/thread evidence. Traced heredoc ordering and continuations, nested shell/quote frontiers, commandless wrappers, eval versus child-shell startup scope, bounded literal printf reconstruction, Python token/UTF-8 consumer proof, marker context fallback, and browser dependency/receiver resolution. The release reviewer independently confirmed the shadowed-undefined correction is absent here and present in #958. The PR's author-reported Python 3.12/3.13, wheel/source and scan validation concerns earlier snapshots; it was not rerun. Refreshed metadata confirms the same head, non-draft status and MERGEABLE/UNSTABLE, with no hosted checks listed for this exact head. No contributor code, tests, imports, builds, scanner invocations, supplied snippets or runtime probes were executed.
|
A related closing-quote ownership case remains reproducible on this head Minimal reproduction through the actual static runner (the strings are analysis input; no shell commands are executed): from skillspector.nodes.analyzers import static_patterns_tool_misuse as tool, static_runner
for path, text in [
("example.json", '{"x":"a del b"}'),
("example.sh", 'echo "a del b"'),
]:
result = static_runner.run_static_patterns_with_ledger(
{"components": [path], "file_cache": {path: text}}, [tool]
)
print(path, result["inspection_ledger"])Both harmless, balanced inputs currently produce We have a bounded candidate that passes all 19 focused controls and the same 293 selected current-main parser/security tests that pass on untouched main, with matching measured dependency sets and unchanged limits. It preserves real inner destructive-command findings, malformed/unknown-consumer/span limitations and incomplete-fragment handling. Two extra controls from the existing reconstruction work caught a regression in the initial candidate: This also reproduces in ClawScan's pinned compatibility transport. On one unchanged 128-file publisher original, static fully-inspected components improve 105/127 →119/127, removing exactly 14 quote gaps; all 26 raw finding payloads remain. Five JavaScript files, two HTML scripts and an offline vulnerability-service limitation remain partial. These are static parser results, not full model/security acceptance. The comparison environment is recorded but is not a claim of a full upstream production lockfile installation. The complete source and transport candidate is now awaiting independent review. I’ll attach the reviewed fix and regression patch here once that finishes; no request to merge or relax inspection/security gates is implied. |
|
Confirmed the shadowed- Using the existing browser fixture, an unknown caller is treated differently solely because the receiver parameter is named
All four controls retain zero findings. The issue is the ownership/completeness claim for an unknown receiver; this does not establish a combined clean verdict or execute the generated program. The exercised reproduction seam, from the repository root with its test dependencies available: from pathlib import Path
import importlib.util
from skillspector import python_tokens
from skillspector.nodes.analyzers import static_patterns_tool_misuse as tool, static_runner
path = Path("tests/nodes/analyzers/test_host_language_shell_ownership.py")
spec = importlib.util.spec_from_file_location("upstream_fixture", path)
fixture = importlib.util.module_from_spec(spec)
spec.loader.exec_module(fixture)
for binding, argument in [("values", "rows"), ("undefined", "rows"),
("values", "external"), ("undefined", "external")]:
assignment = fixture._BROWSER_ASSIGNMENT.replace("rows.map", binding + ".map")
script = fixture._BROWSER_SCRIPT.replace(
fixture._BROWSER_ASSIGNMENT,
"function renderList(" + binding + ") {\n" + assignment
+ "\n}\nrenderList(" + argument + ");",
)
text = fixture._browser_source(script)
projected = python_tokens.python_browser_template_shell_text(text, lambda: None)
result = static_runner.run_static_patterns_with_ledger(
{"components": ["scripts/page.py"], "file_cache": {"scripts/page.py": text}}, [tool]
)
changed = sum(a != b for a, b in zip(text, projected, strict=True))
print(binding, argument, changed, result["inspection_ledger"][0]["outcome"])Supporting environment: Python 3.12.16, Separately, the bounded shell-fence/quote work in this PR resolves our unchanged one-file Markdown regression; the earlier closing-quote reproduction above and a standalone HTML interpolation case remain partial. We are evaluating a narrow shell-fence compatibility backport while keeping browser ownership out until this negative control is addressed. No whole-PR adoption or production recovery is implied. |
rng1995
left a comment
There was a problem hiding this comment.
[SkillSpector Review]
Value and readiness
This head has the same patch and the same twelve changed source/test files as the previously reviewed head. The browser binding blocker remains open; the new commit identity does not change the required correction.
Material findings
Still open — src/skillspector/javascript_tokens.py:1137: ordinary() accepts the shadowable identifier undefined as a primitive before checking its binding. In the existing browser fixture, put the display assignment inside function renderList(undefined) { ... }, replace rows.map with undefined.map, and call renderList(external). The unknown caller-supplied receiver bypasses parameter/argument provenance, including the final native-call dependency audit, so selected backticks can receive ownership where the scanner must retain incomplete inspection. Route the identifier through binding resolution and add parameter/local-constant known-versus-unknown receiver controls. No new findings; the earlier blocker is unchanged. The correction present in #958 is still absent from this PR's source.
PIC tradeoffs
The broad quote/token refinements and their conservative fallbacks remain as previously reviewed. Raw finding bytes staying visible does not establish complete inspection of an unknown consumer. The disclosed ten-file workflow acceptance gap also remains in the description.
Verification and gaps
Re-reviewed exact head 643d912663406a6b2a3aa1646e0f161212766ad6, every review and available comment/thread, and the complete current patch against the prior full assessment. Compared pinned bytes for all twelve changed files and the full diff: all are identical to reviewed head d781e77828c8df4ea42ce7a4a9858d656dd75b8b; source-comparison.json records the file hashes and equality checks. Rechecked the primitive branch, binding resolver, dependency audit, missing regression controls and prior source trace. No hosted checks are listed for this exact head. No contributor code, tests, imports, builds, scanner invocations, supplied snippets or runtime probes were executed.
Backport the browser binding correction and four regression controls from release commit 41ac82c. Unknown receivers keep incomplete inspection; proven data receivers retain delimiter ownership. Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
Use proven shell and validated JSON string boundaries for literal removal operands. Preserve reconstruction uncertainty, raw destructive findings, fragment and span limits, and runtime cancellation. Use an unowned text control for Perl ownership tests now that complete shell source has its own quote proof. Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com>
rng1995
left a comment
There was a problem hiding this comment.
[SkillSpector Review]
Value and readiness
The prior browser binding blocker is resolved at this head. The shell/browser ownership work improves inspection of balanced literals while retaining raw security findings and conservative handling for unresolved executable inputs. I approve the code reviewed at 3a006ede601110fafbb4745dcf95d2d6e7d43b75; all six current-head hosted CI checks pass.
Material findings
Resolved — shadowed undefined browser receiver proof. ordinary() now accepts only true/false/null as spelling-based primitives; undefined proceeds through lexical binding and dependency resolution (src/skillspector/javascript_tokens.py:1142). The paired regression at tests/nodes/analyzers/test_host_language_shell_ownership.py:1036 covers both a parameter and local constant, with known JSON rows versus an unknown external receiver. The unknown cases retain unchanged source and STATIC_PARSE_LIMIT, while proven data keeps the intended template ownership. This closes the issue in both earlier marked reviews.
The author-thread closing-quote report is also addressed. A proven enclosing shell/validated-JSON closer can bound literal removal-word operands without treating that closer as another opener. Added controls retain actual destructive findings and partial results for reconstructed command words, dynamic operands, substitutions, malformed input and parser limits. An exhausted earlier candidate no longer advances the destructive-candidate watermark over later executable text, and those candidate scans now check the analysis deadline. I found no additional required correction in the complete increment and integration context.
PIC tradeoffs
Priority remains P0 because ownership affects security inspection completeness and finding preservation. The refinements retain offset-preserving projections and bounded proofs; unsupported consumers, ambiguous quoting, transformed child commands and unknown startup behavior remain conservative. The inherited JavaScript/comment/Perl changes were checked together with this PR's shell and browser paths; changing Perl test comparison controls to generic text preserves their unowned negative control now that complete shell source has its own quote proof. The disclosed generated-command workflow remains 9/10 inspected and remains visibly partial; approval does not treat that separate unsupported workflow as completed.
Verification and gaps
Compared the complete current patch and all saved source/test bytes with the preceding completed reviews, read the full saved since-review increment and surrounding binding, dependency-audit, quote, operand, child-shell, Markdown/JSON and ledger paths, and checked the new regression assertions. Verified all 13 saved changed files against the Git blob IDs in the exact commit tree; pinned-source-proof.json records every match. The prior Python/reconstruction changes retain their earlier reviewed bytes. Available comments and both marked reviews were reconciled; the retrieved review-thread list is empty.
Fresh metadata still identifies this exact non-draft head, with successful changes, lint, unit/coverage, TypeScript, DCO and Docker smoke checks in run 41389884368. GitHub currently reports MERGEABLE/BLOCKED and the earlier changes-requested review remains recorded pending this reassessment; final merge gates are separate. Fresh static source/wheel and real-skill validation described by the author was inspected as reported evidence, while earlier live-provider runs concern older revisions. No contributor code, tests, imports, builds, supplied snippets, scanner invocations or runtime probes were executed in this review.
* fix(static): preserve enclosing quotes in marker scope analysis Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): retain proven shell quote closing positions Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): keep shell ownership within proven source regions Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): bound heredocs and nested shell command ownership Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): inspect Python string bodies independently of delimiters Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): prove bounded heredoc and f-string literal ownership Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): reset marker context at proven Python string closers Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): retain conservative embedded-language coverage and bound headers Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): require balanced wrapper proof for marker quote context Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): bound literal command quote proof work Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): preserve active and concatenated marker limitations Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(static): select bounded quote proofs and retain ambiguous action cues Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * style: format static ownership regressions Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * Defer Python shell ownership for ordinary short source Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * Recognize bounded literal printf comparison operands Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * Skip empty shell clauses in builtin override proof Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * Keep shell comparison proof bounded across empty clauses Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * Format shell comparison ownership refinements Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * Bound comparison override checks and recognize continued definitions Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * Retain uncertainty for truncated function declarations Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * Remove unproven builtin comparison exemption Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * style: format shell startup regression case Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * Preserve generated browser text and shell execution context Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(parser): resolve shadowed undefined through browser bindings Backport the browser binding correction and four regression controls from release commit 41ac82c. Unknown receivers keep incomplete inspection; proven data receivers retain delimiter ownership. Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> * fix(parser): bound quoted operands without hiding later commands Use proven shell and validated JSON string boundaries for literal removal operands. Preserve reconstruction uncertainty, raw destructive findings, fragment and span limits, and runtime cancellation. Use an unowned text control for Perl ownership tests now that complete shell source has its own quote proof. Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> --------- Signed-off-by: yashrajbasav <yashrajbasav@nvidia.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> (cherry picked from commit 583a68c) Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Valid nested shell quotes, Python string markers, and Python-generated browser templates can be mistaken for executable boundaries, leaving inspectable files marked
static_parse_limit. Preserve proven language boundaries while continuing to inspect the original text for security findings.The change:
evaland child shells.undefinedcorrection from #958. Parameters and local constants resolve through their actual bindings; known JSON data and unknown receivers have paired regression tests.{"x":"a del b"},echo "a del b", and therm/erasevariants. Embedded substitutions, malformed containers, incomplete fragments, and input limits retain conservative handling.main, retaining its JavaScript template parser and comment-handling fixes.Validation of the updated source and package:
src/andtests/.45eb37e8; the full unit-test job is still running: CI run.Earlier live-provider evidence belongs to an older revision: 15 scans across 12 skill directories completed all planned AI analysis, making 584 real provider requests. Those provider scans were not rerun for this static-parser update; the fresh real-skill scans above used
--no-llm.Remaining limitation: one ten-file workflow assembles executable commands from sibling-file extracts and runtime values. Its unresolved file remains partial. Resolving that requires bounded cross-file reconstruction or a skill-side change to use fixed child programs with data passed as arguments; this PR does not waive that warning or claim global detection completeness.
Target:
main. No merge or release is included. The existing changes-requested review needs reassessment against the updated head.