Skip to content

fix: anchor exclusion regex patterns (empty CPG on jssrc2cpg); bump Joern to v4.0.581#24

Merged
Lekssays merged 1 commit into
mainfrom
fix/exclude-regex-unanchored-issue-23
Jul 15, 2026
Merged

fix: anchor exclusion regex patterns (empty CPG on jssrc2cpg); bump Joern to v4.0.581#24
Lekssays merged 1 commit into
mainfrom
fix/exclude-regex-unanchored-issue-23

Conversation

@Lekssays

Copy link
Copy Markdown
Owner

Summary

Fixes #23. The default cpg.exclusion_patterns were written assuming --exclude-regex is full-matched against a path. That holds for the JVM-native frontends (c2cpg, javasrc2cpg, pysrc2cpg — Scala Regex.matches against the relative path) but not for astgen frontends like jssrc2cpg, which apply the same string via plain RegExp.test() — an unanchored substring search — against the file's absolute path.

Under substring search a bare token such as \..* degenerates into "any path containing a .", so index.js (and effectively every real source file) was silently excluded, yielding a completely empty CPG that codebadger's own load-verification then flagged as broken (0 user-defined methods).

Fix

Anchor every token with a leading (?:^|.*/) boundary (start-of-string or a literal /), collapsing the old .*/X + bare-X pairs into one entry each:

# before
- ".*/\\..*"
- "\\..*"
- ".*/test.*"
- "test.*"
# after
- "(?:^|.*/)\\..*"
- "(?:^|.*/)test.*"

This matches a whole path component under both regimes. It is a no-op for the JVM frontends and additionally closes a pre-existing gap where root-level dirs (e.g. vendor/, tmp/, docs/) weren't matched because the bare .*/ prefix required a leading path segment.

Applied to both sources of the defaults: src/defaults.py (EXCLUSION_PATTERNS) and config.example.yaml (cpg.exclusion_patterns). Also aligned config.example.yaml's doc?docs? with src/defaults.py.

The consumers (cpg_generator._escape_regex_pattern, core_tools) only validate that each pattern compiles and pass it through joined with |; (?:^|.*/) is valid regex, so it is preserved intact.

Also

  • Bump JOERN_VERSION 4.0.5554.0.581 in Dockerfile (image rebuilt).

Verification

Simulated both regimes (JVM fullmatch on relative paths, astgen search on absolute paths):

  • Kept: index.js, src/math.js, latest.js, attestation.go, main.c, README_index.js
  • Dropped (both regimes): .git/, test/, src/test/, node_modules/, vendor/, spec.js, docs/, build/out/, tmp/

Existing tests/test_cpg_generator.py (13 tests) still pass.

🤖 Generated with Claude Code

The default `cpg.exclusion_patterns` assumed `--exclude-regex` is
full-matched against the path. That holds for the JVM frontends
(c2cpg, javasrc2cpg, pysrc2cpg — Scala `Regex.matches` against the
RELATIVE path) but not for astgen frontends like jssrc2cpg, which run
plain `RegExp.test()` — an UNANCHORED substring search — against the
file's ABSOLUTE path.

Under substring search a bare token such as `\..*` degenerates into
"any path containing a `.`", so `index.js` (and effectively every real
source file) was silently excluded, producing a completely empty CPG
that load-verification then flagged as broken.

Anchor every token with a leading `(?:^|.*/)` boundary (start-of-string
OR a literal `/`) and collapse the old `.*/X` + bare-`X` pairs into one
entry each. This matches a whole path component under both regimes,
is a no-op for the JVM frontends, and additionally fixes a pre-existing
gap where root-level dirs (e.g. `vendor/`, `tmp/`) weren't matched
because the bare `.*/` prefix required a leading path segment. Also
aligns config.example.yaml's `doc?` -> `docs?` with src/defaults.py.

Bump JOERN_VERSION 4.0.555 -> 4.0.581.

Fixes #23

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Lekssays
Lekssays merged commit 7c7b391 into main Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exclude regex patterns are unanchored

1 participant