Repository navigation
fix(custom-commands): match whole-word phrases without a dynamic RegExp - #1503
Conversation
Semgrep's blocking detect-non-literal-regexp rule flags containsPhrase in loader.ts, which fails the Semgrep job on every PR branched from main since 4002073. The phrase was already escaped, so the finding is a false positive, but the scanner cannot see that. Replace the RegExp with an indexOf scan that keeps the same behaviour: case-insensitive, and a match must not touch [a-z0-9] on either side, so the tag `test` still does not match "latest". Extend the whole-word test to cover a later whole-word hit after an embedded one.
No changeset foundThis PR does not add a changeset, so it will not appear in the changelog or trigger a release. If the change is user-facing, add one: pnpm changesetPick a bump (patch / minor / major) and write the changelog entry in our usual voice ("Added X... Thanks to @you. Closes #123."), then commit the generated If this PR is docs-only or a chore that needs no release note, you can ignore this — or run |
nc-review: comments — 1 nit@addyCooks — a few things worth a look, none blocking. The PR replaces a dynamic ⚪ nit · The new 🔴 blocking · 🟠 a reviewer would ask for a change · ⚪ optional Automated code review — correctness, security, design, tests, plus duplicates and scope. A human still decides; this is not a substitute for review and is not exhaustive. The required status checks separately cover lint, formatting, types, unused dependencies, the test suite and the build. This bot never merges. Maintainers can rerun with |
Every caller already passes the request lowercased (requestLower), so containsPhrase no longer lowercases the haystack a second time. The parameter is renamed haystackLower and the doc comment states that the caller supplies it lowercased.
|
Thanks for the PR @addyCooks |
|
Thanks @akramcodez : ) |
Description
Semgrep's blocking
detect-non-literal-regexprule flagscontainsPhraseinsource/custom-commands/loader.ts, which fails the Semgrep job on every PR branched frommainsince 4002073 (e.g. #1501). The phrase was already escaped before it reachedRegExp, so the finding is a false positive, but the scanner can't see that.This replaces the
RegExpwith anindexOfscan that keeps the same behaviour: matching is case-insensitive, and a match must not touch[a-z0-9]on either side, so the tagteststill does not match "latest". The finding goes away instead of being hidden with anosemgrepcomment.The existing whole-word test is extended to cover a later whole-word hit after an embedded one (
the latest TEST.).Type of Change
Changeset
pnpm changeset) describing this change for the changelogNot needed: internal refactor with no user-facing change.
Testing
Automated Tests
.spec.ts/tsxfiles (extends the existing whole-word test inloader.spec.ts)pnpm test:allcompletes successfully) (see notes below)Notes: run on Windows 11 against this commit.
test:format,test:types,test:types:vscode,test:lint,test:knipandtest:auditpass.loader.tsfinding is gone. Locally it still reports 4detect-child-processfindings (Semgrep 1.175.0) incustom-tools/handler.ts,services/bash-sandbox.tsandtools/git/utils.ts. This PR doesn't touch those files, and CI doesn't report them.loader.spec.tsand every custom-commands and skills spec pass. The remaining failures are Windows-specific (paths, Unix sockets, POSIX process groups, shell scripts). 94 failures are identical on unmodifiedmain(9b78cdd5). The only difference is one UI test that failed here once and passes 3/3 when re-run alone, while 13 others fail only onmain. CI on Linux is the authoritative run.Manual Testing
Not applicable: this is a pure string helper with no provider or MCP involvement.
Checklist