Skip to content

js-imports rule only matches double-quoted require()/import — single-quoted CommonJS invisible to --importers #147

Description

@nicknsheth-beep

Summary

scanner/sg-rules/javascript.yml's js-imports rule only matches double-quoted import/require string literals. Single-quoted CommonJS require() calls — extremely common in real-world JS, and the default style under most Prettier/ESLint configs (singleQuote: true) — are silently invisible to --importers / the MCP get_importers tool, which then reports a confident "No files import X" for files that are demonstrably imported elsewhere.

This is a correctness issue, not just a wording one: it produces a confident false negative on exactly the kind of blast-radius check someone runs before editing a shared/security-sensitive file.

Root cause

scanner/sg-rules/javascript.yml:

id: js-imports
language: javascript
rule:
  any:
    - pattern: import $$$_ from "$PATH"
    - pattern: import "$PATH"
    - pattern: require("$PATH")

All three patterns are literal-text ast-grep patterns hardcoded to double-quoted strings. Verified directly with ast-grep (0.45.1) against this exact rule:

// single.js
const memberRoutes = require('./routes/members');

ast-grep scan --rule rule.yml single.js produces zero matches.

// double.js
const memberRoutes = require("./routes/members");

→ produces a match.

By contrast, scanner/sg-rules/typescript.yml / tsx.yml / jsx.yml all use a structural, quote-agnostic rule:

id: ts-imports
language: typescript
rule:
  kind: import_statement

which correctly matches regardless of quote style. Only the plain .js rule uses literal-text patterns, and only for double quotes.

Impact

On a real Node/Express codebase (100% single-quoted require() throughout — the standard style), this means codemap --importers <any-required-file>.js reports zero importers for files that have many. Confirmed on two separate repos, e.g. services/layoutInputService.js — 14 real requirers via grep -rn "require(.*layoutInputService", codemap --importers reports "No files import services/layoutInputService.js."

Separately (already fixed as of current main, noting for context): codemap v4.4.0's renderImportersReportCLI printed the "Go resolves imports at package level" explanatory note unconditionally on every zero-importer result, regardless of file extension — confirmed by diffing blast_radius.go at the v4.4.0 tag vs current main, where it's now gated behind filepath.Ext(report.File) == ".go". That fix (presumably landed in v4.4.2, "Add Go parser fallback" (#123), the last commit to touch that file) stops the misleading wording, but doesn't touch this quote-style detection gap — upgrading alone won't fix the false negative described above.

Suggested fix

Match both quote styles (and ideally template-literal requires) in javascript.yml, e.g.:

rule:
  any:
    - pattern: import $$$_ from "$PATH"
    - pattern: import $$$_ from '$PATH'
    - pattern: import "$PATH"
    - pattern: import '$PATH'
    - pattern: require("$PATH")
    - pattern: require('$PATH')

or better, switch to a structural kind:-based rule the way typescript.yml/tsx.yml/jsx.yml already do, so quote style stops being a concern entirely.

Environment

  • codemap 4.4.0 (also reproduced against scanner/sg-rules/javascript.yml and blast_radius.go as they currently stand on main)
  • ast-grep 0.45.1
  • macOS, Homebrew install (jordancoin/tap/codemap)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions