Minor Changes
-
#4277
5310734Thanks @williamzujkowski! - feat(security): polyglot (Python/Go) ast-grep QA/security rules via read-only runAstQaRules (#4249 child C)Adds a new read-only
runAstQaRulesrunner (security/ast-rule-runner.ts,
exported fromexports/security.ts) that runs YAML-defined@ast-grep/napi
rules against Python/Go source, detecting dynamiceval/exec, shell
injection (os.system/subprocess(..., shell=True)), and unchecked external
command execution (exec.Command). Ships three built-in rules under
security/ast-rules/*.ymlplus fixtures with both positive hits and
near-miss negatives (evaluate/executor/no-shell=True/localCommand
helper/aliasedmyexec.Command), mirroring the #4243 lesson that a rule
which "sort of" matches over-fires on lookalikes.@ast-grep/napi@0.44.1'sLangenum has no Python/Go, so this adds the
dynamic-language grammar packages@ast-grep/lang-python@0.0.6and
@ast-grep/lang-go@0.0.6(both EXACT-pinned — early/experimental packages
where a caret range could silently swap in an incompatible native.so
grammar build) and registers them once per process via a lazy
ensurePolyglotLangs()singleton, since napi's@experimental registerDynamicLanguagethrows if called more than once. Both grammar
packages are added to tsup'sexternallist — like the other native-addon
deps — since they resolve their prebuilt.sovia a__dirname-relative
lookup that bundling would break.Detection-only by construction: ast-grep's YAML
fix:key is never read by
SgNode.findAll(only ast-grep's separate CLI/rewrite machinery applies it),
so this runner cannot become a writer even if a rule author adds one.MCP exposure is deferred to a follow-up issue to keep this surface a plain
function until a named consumer needs it wired through a tool.
Patch Changes
-
#4274
5a13b17Thanks @williamzujkowski! - fix: ast-fixer misses semicolon-terminated promise chains and over-matches*Functioncallees (#4243); rewrites now ast-grep pattern-basedThe
error-handlingfixer's regex only matched a trailing)with no
semicolon, so any semicolon-terminated.then(...)chain (the overwhelmingly
common case) silently fell back to a TODO comment instead of getting a
.catch(...). Theno-evalfixer'sexpressionText.endsWith('Function')
check over-matched ordinary identifiers likesetupFunction().Both transforms are replaced with
@ast-grep/napipattern rewrites
(agents/collaboration/ast-rewrites.ts):.catch(...)is appended to the
outermost unhandled.then(...)of a chain (ast-grep matches the
call_expressionnode itself, whose text excludes the trailing;, so this
bug class cannot recur by construction), andeval(...)/Function(...)/
new Function(...)are matched by exact callee so a*Function-suffixed
identifier cannot over-match. The other four ts-morph fixers, and
AstFixer's entire public surface (applyFix,createAstFixer(),
AstFixResult, comment-fallback, line-targeting), are unchanged. Zero new
dependencies —@ast-grep/napiwas already pinned forsearch_usages(#4265).