Your dry-run verification step is solid, but be careful with the `--verbose` flag's output format across CLI versions. We've seen the "Processing file" log line change to "Scanning file" in a patch update, which broke our grep pattern and gave a false positive on the ignore file's effectiveness.
For the project-specific suppression validation, our CI step also checks that the referenced paths are not symlinks outside the project boundary. We had a monorepo setup where a suppressed path was a symlink to a shared library in a parent directory, which effectively bypassed the containment check.
data is the product
The "set Project Type to JavaScript/TypeScript" tip is a classic example of a vendor checkbox that doesn't do what you think. In our last audit, that setting applied a predefined, non-transparent filter to certain query categories. It wasn't just enabling engines, it was silently downgrading the scan scope based on some internal checklist. We found more actionable issues by leaving it on "Multi-Language" and manually controlling the engines, which Checkmarx support confirmed was the "advanced" path. So much for a simple dropdown.
— skeptical but fair
Agreed on the core principle of filtering noise, but I'd push back on the third-party library blanket suppression. That pattern can hide vulnerabilities in *vendored* dependencies, which are still in your node_modules but represent your actual deployed risk.
For test file patterns, you might also want to include `**/__tests__/**` directory structures, which are common in Jest setups. The `.d.ts` exclusion is solid though - those are rarely the source of a runtime issue.
Every dollar counts.
You've put your finger on the core architectural dissonance. A clean scan of source becomes a dangerously misleading metric when the executed artifact is a transformed bundle.
We validate this gap by running dependency-check scans on our production bundles via their source map, which often flags transitive vulnerabilities that Checkmarx misses entirely. The model mismatch creates a risk illusion; you're measuring the security of your development environment, not the deployment. This forces a dual-scan strategy: SAST for the source we write, SCA on the bundle we ship, with a manual reconciliation step that is itself error-prone.
Data never lies.
Great additions to the ignore list. The sheer number of dot-config files in a modern JS project is wild.
Just a heads up on >push the scan earlier to the source stage. If your CI is scanning a branch before a PR merge, make sure you're scanning the *merged* state against your target branch, not just the feature branch source. We got burned once where a dependency update in main wasn't reflected in the branch scan, so a vulnerability slipped through.
That dual-scan strategy other folks mentioned is sounding more necessary every day.
Cheers, Henry
The first two steps are absolutely foundational, but I think that third step about blanket suppression by path is where a lot of teams paint themselves into a corner. Suppressing `**/node_modules/**` by pattern is convenient, but it creates a policy blind spot for *vendored* or checked-in libraries, which do represent your deployed risk even though they're in that folder structure.
We made that mistake early on. Our policy now is to only suppress third-party findings after a manual review confirms it's an upstream library we can't patch, and we log that as a risk acceptance. It's more work, but it stops us from accidentally hiding a library we forked and modified internally.
buyer beware, but buy smart
The dry-run verification is a good first step, but I've found you need to validate the ignore file's *content*, not just that it's being read. Our script also checks that the .cxignore doesn't contain overly broad patterns like `**/*.js` which would cripple the scan. It's easy for someone to cargo-cult an ignore list and nuke the actual target files.
On suppression files, your containment check is smart. We take it a step further and have the CI job reject any suppression that references a path matching a `.gitignore` pattern. If it's ignored by git, it shouldn't be in the source tree to be suppressed in the first place; that's usually a sign of a messed up workspace or a scan pointed at the wrong directory.
Benchmarks or bust
Agreed on the ignore list, but careful with the >Set Project Type to "JavaScript/TypeScript" step. That checkbox often applies hidden scope filters. We leave ours on "Multi-Language" and manually toggle engines. More control, less magic.
Also, suppressing `**/node_modules/**` can hide risks in vendored dependencies you've modified. We only suppress third-party findings after a review and document the accepted risk. It's more upfront work, but it prevents nasty surprises later.
Your core advice on `.cxignore` patterns is correct, but I'd caution against blindly applying the `**/node_modules/**` suppression in the query management section. That's a global policy that will mask vulnerabilities in any library you've intentionally vendored or forked and placed within that structure, which is a legitimate deployment artifact. It conflates source-level scanning with dependency analysis.
The engine tuning is accurate for React, though for Vue 3 with `` you might also need to ensure the parser is handling the composition API syntax correctly; I've seen some older engine versions trip on the syntactic sugar and miss entire script blocks, yielding a false negative on scan completeness.
The `Set Project Type to "JavaScript/TypeScript"` step is more nuanced than it appears. As others have noted, that setting can apply opaque filters. I've verified with their support that it can automatically deselect certain language-agnostic queries (like some insecure randomness or cryptographic weakness checks) under the assumption they don't apply to JS. Always verify the actual query list after applying that project type.
You're spot on about the Vue 3 composition API parser issue. We had the same experience last quarter; the scan report showed suspiciously few findings for a large codebase. We traced it to the engine's script block extraction failing on `setup()` syntax, which meant entire components weren't being analyzed. The fix was to validate the "Lines of Code Scanned" metric against our source count and update the engine version - a step that should be in every checklist.
The point about >a legitimate deployment artifact is critical. It reveals a fundamental gap in SAST tool categorization: the inability to distinguish between a pristine node_module and a modified, vendored library. Our workaround is to maintain a separate scan configuration for any directory containing a forked lib, treating it as first-party code, but it's a manual process that's easy to forget.
Good ignore list. But disabling the obfuscation scanner is a mistake for any customer-facing SPA. Modern bundlers minify and mangle by default. You need to know if your config could leak sensitive data patterns after the build, not just in your source. I keep it on.
Optimize or die.
Oh, that's a really good point about the obfuscation scanner. I hadn't thought about minified production builds. So you're saying even if the source is clean, the final bundled code could accidentally expose something like an API key pattern after minification?
Do you ever get false positives from it, like flagging minified variable names as potential secrets?
It's not false positives you should worry about with minified code, it's false negatives. An obfuscation scanner isn't looking for variable names, it's looking for the residual *patterns* of sensitive data that survive the build process.
If your scanner is flagging random minified strings, it's poorly tuned. The real risk is a dev leaving a hardcoded credential in a config file that gets bundled into a single, mangled production JS file. The source scan might catch it, but the obfuscation scanner confirms the pattern is still present and discoverable in the final asset.
You need to scan the actual build output, not just the source. That's where the exposure happens.
Your cloud bill is 30% too high
Yep, that validation step on "Lines of Code Scanned" is non-negotiable. We had a similar gap with a React codebase using a lot of dynamic imports - the scanner just skipped those files because of a parsing timeout default.
The separate config for forked libraries is a decent band-aid, but it's a policy nightmare to maintain. The real fix would be for SAST tools to add a metadata flag, something like a `.vendor-override` file, to explicitly mark a "node_modules" subdirectory as in-scope.
Spreadsheets > marketing slides.
Absolutely, the >parsing timeout default is a silent killer for coverage. Dynamic imports often trip up scanners because they treat them as conditional execution paths that can't be resolved statically.
Your metadata flag idea is clever. Until tools adopt something like that, we use a pre-scan script to temporarily symlink any modified vendor libs out of their node_modules folder and into a scan-specific directory. It's hacky but keeps the policy simple - node_modules is always suppressed, and our special scan config just points at that temp directory.
Have you seen the newer SAST engines that can follow webpack bundle analysis? They sometimes handle dynamic imports better by understanding the chunk manifest.
catdad