Copy/paste detector for source code. 220+ languages, Rust engine, SARIF/HTML/badge reporters, GitHub Action, MCP server for AI agents.
This report summarizes scanner evidence for kucherenko/jscpd, a Rust project with 6,471 GitHub stars. SynthScan examined 115,702 lines of code across 276 source files, recording 238 pattern matches distributed across 9 syntactic categories. The legacy adjusted pattern signal is 3.3 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 171 finding(s).
Are imports declared and package/API names verified? 1 finding(s).
Are wrappers, guards, and repeated structures necessary? 66 finding(s).
Which changes need focused human review? 238 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 238 distinct pattern matches across 9 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | rust/crates/cpd-tokenizer/tests/behavior.rs | 91 | // ── hostile input ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/tests/behavior.rs | 407 | // ── modes ──────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/tests/behavior.rs | 464 | // ── ignore patterns and markers ───────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/tests/behavior.rs | 709 | // ── multi-format files ───────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/tests/behavior.rs | 754 | // ── TypeScript stripped for cross-format detection ───────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/tests/behavior.rs | 834 | // ── formats ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/tests/behavior.rs | 854 | // ── known bugs ────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/src/javascript.rs | 20 | // ── fallback tokenizer ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/src/javascript.rs | 83 | // ── helpers ────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/src/javascript.rs | 162 | // ── public API ─────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/src/javascript.rs | 268 | // ── ignore markers in JSX ───────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-tokenizer/src/javascript.rs | 424 | // ── tests ───────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 51 | # ── bundlers and dev servers ────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 72 | # ── full-stack and meta frameworks ──────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 415 | # ── application frameworks ──────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 552 | # ── mobile ──────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 583 | # ── serverless and edge ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 646 | # ── documentation and static sites ──────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 683 | # ── component workshops ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 704 | # ── test runners ────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 769 | # ── databases and migrations ────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 806 | # ── other toolchains ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/frameworks.yaml | 832 | # ── Python ──────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/tests/findings.rs | 118 | // ── JavaScript and TypeScript resolution ──────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/tests/findings.rs | 517 | // ── JSX factories ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/tests/findings.rs | 564 | // ── components ───────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/tests/findings.rs | 631 | // ── Python ───────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/tests/findings.rs | 705 | // ── hostile files ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/tests/findings.rs | 791 | // ── more resolution shapes ───────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/framework.rs | 693 | // ── loading ───────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/graph.rs | 561 | // ── queries the report layer asks ─────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/entry.rs | 330 | // ── helpers for manifest readers ──────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/entry.rs | 370 | // ── scripts that name source files ────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/rustc.rs | 191 | // ── cargo's JSON ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/javascript.rs | 284 | // ── resolution ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/javascript.rs | 467 | // ── workspace packages ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/javascript.rs | 626 | // ── bundler config aliases ────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/javascript.rs | 919 | // ── tsconfig path aliases ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/javascript.rs | 1153 | // ── manifests ─────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/javascript.rs | 1331 | // ── parsing ───────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/javascript.rs | 3388 | // ── resolution ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/javascript.rs | 3879 | // ── tsconfig path aliases ─────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/javascript.rs | 4084 | // ── files named by a string rather than imported ──────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/javascript.rs | 4144 | // ── manifests ─────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/sfc.rs | 215 | // ── masking ───────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/sfc.rs | 243 | // ── block scanning ────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/sfc.rs | 416 | // ── markup scanning ───────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/python.rs | 141 | // ── resolution ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/python.rs | 254 | // ── manifests ─────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/python.rs | 322 | // ── parsing ───────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/python.rs | 1287 | // ── forward references ────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/python.rs | 1704 | // ── resolution ────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/basta/src/lang/python.rs | 1828 | // ── manifests ─────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd-reporter/src/deadcode/mod.rs | 126 | // ── helpers shared by the reporters ──────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd/tests/integration.rs | 3616 | // ── Binary name follows the invoked executable ────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd/tests/integration.rs | 3667 | // ── exit codes (#1047) ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd/tests/integration.rs | 3667 | // ── exit codes (#1047) ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | rust/crates/cpd/tests/integration.rs | 3788 | // ── --history: duplication trend over git history (#1002) ───────────────── | COMMENT |
| MEDIUM | rust/crates/cpd/tests/integration.rs | 3788 | // ── --history: duplication trend over git history (#1002) ───────────────── | COMMENT |
| MEDIUM | .github/workflows/release.yml | 23 | # ─── Detect changed paths & pending releases ────────────────────────── | COMMENT |
| 6 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | rust/crates/cpd-tokenizer/src/generic.rs | 61 | // and `::` (batch), `*>` (COBOL), `NB.` (J), `BTW` | COMMENT |
| LOW | rust/crates/cpd-tokenizer/src/tokenizer.rs | 41 | COMMENT | |
| LOW | rust/crates/cpd-tokenizer/src/tokenizer.rs | 61 | /// function or type names match (issue #998). Keywords are kept: the | COMMENT |
| LOW | rust/crates/cpd-tokenizer/src/tokenizer.rs | 181 | /// Push a token into the detection output if it passes all filters. | COMMENT |
| LOW | rust/crates/cpd-tokenizer/src/tokenizer.rs | 301 | /// them consistently (see [`DetectionToken::name`]). | COMMENT |
| LOW | rust/crates/cpd-tokenizer/src/tokenizer.rs | 401 | ]; | COMMENT |
| LOW | rust/crates/cpd-tokenizer/src/tokenizer.rs | 801 | Mode::Strict => true, | COMMENT |
| LOW | rust/crates/cpd-tokenizer/src/ts_strip.rs | 1 | // cpd-tokenizer: collect byte spans of erasable TypeScript-only syntax. | COMMENT |
| LOW | rust/crates/basta/frameworks.yaml | 1 | # Frameworks basta recognises, and what each one starts without an import. | COMMENT |
| LOW | rust/crates/basta/frameworks.yaml | 21 | # packageJsonKeys package.json has this top-level section | COMMENT |
| LOW | rust/crates/basta/frameworks.yaml | 41 | # anybody's word everywhere else. | COMMENT |
| LOW | rust/crates/basta/src/framework.rs | 1 | //! Frameworks: the programs that start a project's files without importing them. | COMMENT |
| LOW | rust/crates/basta/src/framework.rs | 41 | ]; | COMMENT |
| LOW | rust/crates/basta/src/framework.rs | 61 | /// Directories the framework loads whole. | COMMENT |
| LOW | rust/crates/basta/src/section.rs | 1 | //! The dead-code section of a jscpd config file. | COMMENT |
| LOW | rust/crates/basta/src/section.rs | 41 | /// Dead-code settings a project keeps in its jscpd config. | COMMENT |
| LOW | rust/crates/basta/src/section.rs | 61 | pub include_tests: Option<bool>, | COMMENT |
| LOW | rust/crates/basta/src/classify.rs | 1 | //! Turning a resolved graph into the findings a reader acts on. | COMMENT |
| LOW | rust/crates/basta/src/classify.rs | 121 | /// Which rule, if any, a declaration falls under. | COMMENT |
| LOW | rust/crates/basta/src/classify.rs | 141 | // in `phases.py` itself ever mentions it again. | COMMENT |
| LOW | rust/crates/basta/src/graph.rs | 1 | //! The whole-project view: which module every specifier names, which | COMMENT |
| LOW | rust/crates/basta/src/graph.rs | 41 | /// Target module of each import, parallel to [`Graph::imports`]. | COMMENT |
| LOW | rust/crates/basta/src/resolve.rs | 1 | //! The index every resolver answers against, and the path arithmetic they | COMMENT |
| LOW | rust/crates/basta/src/resolve.rs | 21 | /// One import path alias a project declares for itself. | COMMENT |
| LOW | rust/crates/basta/src/resolve.rs | 61 | /// | COMMENT |
| LOW | rust/crates/basta/src/config.rs | 21 | /// The frameworks this run can recognise, and whether it should try. | COMMENT |
| LOW | rust/crates/basta/src/config.rs | 41 | pub min_lines: u32, | COMMENT |
| LOW | rust/crates/basta/src/confidence.rs | 1 | //! How sure basta is that a finding is really dead. | COMMENT |
| LOW | rust/crates/basta/src/confidence.rs | 41 | /// The finding itself is inside a test, fixture or example file. | COMMENT |
| LOW | rust/crates/basta/src/finding.rs | 1 | //! What a run reports. | COMMENT |
| LOW | rust/crates/basta/src/entry.rs | 1 | //! Where the program starts. | COMMENT |
| LOW | rust/crates/basta/src/entry.rs | 21 | //! that names a source file runs it, copies it or ships it. Those files | COMMENT |
| LOW | rust/crates/basta/src/entry.rs | 401 | const SCRIPT_SIZE_LIMIT: u64 = 1024 * 1024; | COMMENT |
| LOW | rust/crates/basta/src/test_scan.rs | 1 | //! Building a resolved [`Graph`] from source strings, for tests. | COMMENT |
| LOW | rust/crates/basta/src/model.rs | 1 | //! The data model shared by every language analyzer and by the graph. | COMMENT |
| LOW | rust/crates/basta/src/model.rs | 21 | COMMENT | |
| LOW | rust/crates/basta/src/model.rs | 41 | /// A TypeScript `export type` / `import type` binding: erased at runtime. | COMMENT |
| LOW | rust/crates/basta/src/model.rs | 61 | /// An abstract declaration — the implementation lives in subclasses. | COMMENT |
| LOW | rust/crates/basta/src/model.rs | 141 | pub is_entry: bool, | COMMENT |
| LOW | rust/crates/basta/src/model.rs | 161 | /// The file exists to re-export a package's surface (`index.ts`, | COMMENT |
| LOW | rust/crates/basta/src/model.rs | 221 | /// The local binding the import creates, when it creates one. `None` for | COMMENT |
| LOW | rust/crates/basta/src/model.rs | 241 | StarReExport, | COMMENT |
| LOW | rust/crates/basta/src/rustc.rs | 1 | //! Rust dead code, read from the compiler. | COMMENT |
| LOW | rust/crates/basta/src/cli.rs | 41 | COMMENT | |
| LOW | rust/crates/basta/src/cli.rs | 61 | /// Treat this framework as present at the scan roots (repeatable) | COMMENT |
| LOW | rust/crates/basta/src/lang/mod.rs | 1 | //! Language plug-ins. | COMMENT |
| LOW | rust/crates/basta/src/lang/mod.rs | 61 | /// error: one broken file must not fail the run, but the graph has to | COMMENT |
| LOW | rust/crates/basta/src/lang/mod.rs | 121 | COMMENT | |
| LOW | rust/crates/basta/src/lang/javascript.rs | 1 | //! JavaScript, TypeScript, JSX and TSX, through the oxc parser — and the | COMMENT |
| LOW | rust/crates/basta/src/lang/javascript.rs | 1101 | COMMENT | |
| LOW | rust/crates/basta/src/lang/javascript.rs | 1901 | /// walk. See [`CommonJs`]. | COMMENT |
| LOW | rust/crates/basta/src/lang/sfc.rs | 1 | //! Single-file components: Vue, Svelte and Astro. | COMMENT |
| LOW | rust/crates/basta/src/lang/sfc.rs | 41 | pub script: String, | COMMENT |
| LOW | rust/crates/basta/src/lang/python.rs | 1 | //! Python, through the ruff parser. | COMMENT |
| LOW | rust/crates/cpd-semantic/src/test_code.rs | 1 | //! Which functions are tests, so that `--compare` measures tests and code | COMMENT |
| LOW | rust/crates/cpd-semantic/src/units.rs | 1 | //! Functions to embed for semantic clones (`--semantic`). | COMMENT |
| LOW | rust/crates/cpd-semantic/src/lib.rs | 1 | //! Semantic clones for jscpd (`--semantic`, experimental): functions that | COMMENT |
| LOW | rust/crates/cpd-semantic/src/compare.rs | 1 | //! Two codebases compared function by function (`--compare`): a project and | COMMENT |
| LOW | rust/crates/cpd-semantic/src/compare.rs | 21 | //! function of the other side under the same name, once case, | COMMENT |
| LOW | rust/crates/cpd-semantic/src/compare.rs | 441 | } | COMMENT |
| 98 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | README.md | 88 | - **Type-4 semantic clones (experimental)** — `--semantic` embeds the functions of JavaScript, TypeScript, Vue, Svelte, | CODE |
| MEDIUM | rust/crates/cpd-semantic/Cargo.toml | 49 | # The local provider: the embedding model runs in-process. | COMMENT |
| MEDIUM | rust/crates/cpd-semantic/Cargo.toml | 56 | # embedding model's matrix products on macOS. | COMMENT |
| MEDIUM | skills/compare-codebases/SKILL.md | 12 | jscpd finds the functions of JavaScript, TypeScript, JSX, TSX, Vue, Svelte, Astro, Python, Rust, Go, Java, Kotlin, C#, C | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | rust/crates/cpd-reporter/assets/prism/prism.min.js | 195 | !function(a){var n="(?:\r?\n|\r)[ \t]*\\|.+\\|(?:(?!\\|).)*";a.languages.gherkin={pystring:{pattern:/("""|''')[\s\S]+?\1 | CODE |
| MEDIUM | rust/crates/cpd-reporter/assets/prism/prism.min.js | 407 | !function(e){var t=/\$\w+|%[a-z]+%/;e.languages["plant-uml"]={comment:{pattern:/(^[ \t]*)(?:'.*|\/'[\s\S]*?'\/)/m,lookbe | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | rust/crates/basta/frameworks.yaml | 8 | # This file is compiled into the binary. A project adds to it or overrides it | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | rust/crates/cpd-semantic/src/compare.rs | 284 | // Step 1: the rule of --semantic, across the sides, between functions | COMMENT |
| LOW | rust/crates/cpd-semantic/src/compare.rs | 325 | // Step 2: namesakes among the functions left unpaired. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | rust/crates/cpd-semantic/src/compare.rs | 284 | // Step 1: the rule of --semantic, across the sides, between functions | COMMENT |
| LOW | rust/crates/cpd-semantic/src/compare.rs | 325 | // Step 2: namesakes among the functions left unpaired. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | rust/scripts/publish-npm.sh | 4 | # Usage: | COMMENT |
| LOW | rust/scripts/publish-crates.sh | 4 | # Usage: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | rust/scripts/build-pypi-wheels.py | 21 | CODE |