chameleon 2.38.15
Review-skills QA pass: verify every MCP tool the chameleon-pr-review and
chameleon-receiving-code-review skills orchestrate against real repos, and
reconcile the skill instructions with the real tool behavior. Four tool bugs and
eight skill-logic drifts fixed.
Fixed
- The crypto-context gate silently dropped weak-hash / insecure-random on
compound identifiers. The ±200-char gate that decides whether an advisory
weak MD5/SHA1 or a non-cryptographic random is worth surfacing matched its
keywords with word boundaries (\b(password|token|salt|...)\b), so a keyword
that is a snake_case / camelCase component (password_salt,sessionToken,
passwordHash) never matched and the advisory was lost across all three
languages — the dominant crypto-material naming style. The gate now matches
identifier segments (accepting_separators and camelCase transitions) while
still rejecting a keyword buried in an unrelated word (design,tokenizer). - TypeScript weak-hash was dead on the Node crypto API.
crypto.createHash("md5")/createHmac("sha1")is the standard way to request
a weak digest in Node, but the algorithm name lives in a string literal that the
string-stripper blanks before the weak-hash regex runs, so the dominant TS/JS
form never fired. A dedicated pass now reads the algorithm from the raw content,
under the same crypto-context gate. - A malicious install script that starts like a version escaped classification.
scan_dependency_changesdiscriminates a lifecycle script (postinstall) from a
package literally namedpostinstallby whether the value looks like a version.
The check only looked at the value's prefix, so a command starting with a digit
orv+digit (7z x payload && node run.js,0;curl … | sh,2to3 -w,
v8flags) was misread as a dependency and the install-script FIX downgraded
to a dependency NIT. A command now reveals itself by a space, a shell
metacharacter, or a digit-immediately-followed-by-a-letter, regardless of prefix. get_contract_breaksreported "clean" when its calls index was missing. An
absent/corrupt calls index made the tool return no findings withstatus: ok,
indistinguishable from "no contract breaks". It now returnsstatus: degraded
with a reason (mirroringget_callers, which does not present a missing index as
"no callers").- Skill-logic drift reconciled with the real tools (both review skills): the
pr-reviewskill now routesscan_dependency_changes'sminified-manifest
FIX (a supply-chain evasion where every other check was defeated); reads the
refute_findingenveloperefuterfield (adisabledrefuter returns an EMPTY
verdict list, not a per-findingunverified); handles aget_autopass_verdict
status: degradedenvelope (which omitstypecheck/facts/changed_files);
lists all six shipped co-change rules (adding the Django model→migration and
NestJS controller→module pairs); confirms package manifests/lockfiles still get
the pre-archetype secret scan (a hard credential inpackage.jsonmust reach the
BLOCK gate); and defines the round-3 refuter send set by principle
(model-judgment BLOCK/FIX, never an always-NIT finding) instead of a hand-list
that had drifted. Thereceiving-code-reviewskill now applies the same
secret_hardandeval-callseverity gates before letting a lint hit overrule a
reviewer's "this is fine", so a low-precision secret false positive cannot flip a
correct human judgment.