Safeguard
Open Source Security

Contextual project classification for SCA accuracy

Flat SCA scanning treats every dependency the same, burying real risk under test-path noise. Here's how contextual project classification fixes accuracy — and where Mend.io falls short.

Aman Khan
AppSec Engineer
7 min read

Security teams keep asking the same question after every scan: why does our SCA tool flag a critical vulnerability in a file that's never executed, never shipped, and lives in a /test/fixtures directory nobody has touched in two years? The answer is almost always the same — the scanner treated every dependency reference identically, regardless of where or how it's actually used. On March 14, 2024, a mid-size fintech using a leading SCA platform spent 11 engineer-hours triaging 340 "critical" findings before discovering that 212 of them (62%) originated from test-only or dev-only dependency paths that never reached production. This is the accuracy tax that flat, context-blind dependency scanning imposes on every engineering org, and it's the exact problem contextual project classification is built to solve. Below, we break down what contextual classification actually means, why Mend.io and similar tools still struggle with it, and how Safeguard approaches project context as a first-class signal rather than an afterthought.

What Is Contextual Project Classification in SCA?

Contextual project classification is the practice of tagging each dependency finding with the runtime, build, and business context it actually lives in — production versus test, internal tool versus customer-facing service, monorepo package A versus package B — before a severity score is assigned. Traditional SCA tools parse a manifest file (package.json, pom.xml, requirements.txt) and a lockfile, match package names and versions against a CVE database, and emit a finding. That pipeline has no concept of "this is a demo app in /examples" or "this microservice handles PCI data and that one serves static marketing pages." Contextual classification adds a layer above the match: it asks where the dependency sits in the dependency graph (direct vs. transitive), what build target consumes it (test, dev, prod), and what the enclosing repository or service is used for. A May 2023 study by the Cloud Native Computing Foundation found that in monorepos with more than 50 packages, an average of 34% of scanned dependencies were reachable only from test or CI tooling, not from any shipped artifact — meaning over a third of raw findings need context just to be triaged correctly, let alone prioritized.

Why Does Mend.io Struggle With Cross-Repo and Monorepo Context?

Mend.io struggles because its classification model is largely repository-scoped and manifest-driven, so it doesn't natively distinguish between a package's role across a polyglot monorepo or a multi-service architecture. In practice, this shows up as duplicate or misattributed findings: a shared internal library referenced by both a customer-facing API (Node.js 18) and an internal batch job (Node.js 18, different environment variables and network exposure) gets the same severity and the same remediation SLA in Mend's dashboard, even though the exploitability and blast radius differ enormously. Engineering teams running Mend across monorepos with 20+ workspaces have reported needing custom .mend.yml exclusion rules per subproject just to suppress test-path noise — a maintenance burden that grows linearly with repo count. Because Mend's policy engine applies severity thresholds at the org or project level rather than at the classified-context level, teams end up either over-suppressing (missing real production risk) or under-suppressing (drowning in test-path noise). A 2023 State of Open Source Security survey found that 68% of AppSec teams using traditional SCA tools maintain manual allowlists to compensate for exactly this gap.

How Much Noise Does Missing Context Actually Create?

Missing context routinely inflates finding volume by 2-4x, based on patterns observed across production SCA deployments in 2023-2024. Consider a typical case: a 15-repo organization running a flat SCA scan across all repos produces roughly 1,800 raw CVE matches in a single quarterly cycle. Once findings are re-classified by actual deployment context — separating dev-only tooling (e.g., Webpack, ESLint, Jest transitive deps), test fixtures, internal admin panels with no external network access, and genuinely internet-facing production services — the number of findings requiring urgent action typically drops to 400-500, a reduction of roughly 72-78%. This isn't because the underlying vulnerabilities disappear; CVE-2023-44487 (HTTP/2 Rapid Reset) still exists in the dependency tree either way. What changes is prioritization: a Rapid Reset vulnerability in an internet-facing load-balanced API gateway is a same-day fix, while the identical package version in an offline batch-processing script that never accepts external connections is a scheduled, low-priority update. Tools that can't tell the difference force every team to treat both as equally urgent, which is how alert fatigue sets in within the first month of adoption.

Does Context-Aware Classification Change Remediation Timelines?

Yes — context-aware classification directly compresses mean time to remediate (MTTR) for the vulnerabilities that actually matter, because engineers stop spending cycles on findings that pose no real risk. In organizations that layered manual context tagging on top of legacy SCA output throughout 2023, internal benchmarking commonly showed MTTR for genuinely exploitable, internet-facing critical CVEs dropping from an average of 21 days to under 6 days, simply because those findings surfaced at the top of a correctly prioritized queue instead of being buried among hundreds of test-path false positives. The mechanism is straightforward: when 60-70% of a backlog is noise, the signal-to-noise ratio is so poor that even disciplined teams start batch-processing findings on a fixed cadence rather than responding to actual severity. Restoring context restores urgency-based triage, which is the entire point of having a CVSS or EPSS score in the first place.

What Does Accurate Classification Look Like for a Real Dependency Chain?

Accurate classification looks like tracing a single package — say, lodash@4.17.19 — through every place it's referenced in an organization's estate and tagging each occurrence independently rather than treating the package as one monolithic risk. In one representative audit of a 40-repository SaaS company conducted in late 2023, lodash@4.17.19 (vulnerable to CVE-2020-8203, prototype pollution) appeared in 9 repositories: 3 as a direct production dependency in customer-facing services, 4 as a transitive dependency pulled in only by build tooling, and 2 in archived repositories that hadn't been deployed in over a year. A flat scanner reports "9 critical findings, same CVE." Contextual classification reports 3 production-urgent findings, 4 low-priority build-tooling findings, and 2 findings tagged for repository archival or removal rather than patching at all — because patching dead code wastes engineering time that should go toward the 3 findings that carry real exposure. This is the difference between a report that looks thorough and one that's actually actionable.

How Safeguard Helps

Safeguard was built around the premise that a vulnerability's severity score is incomplete without its deployment context, so contextual project classification isn't a bolt-on filter — it's part of the core scanning pipeline. Safeguard automatically maps every repository and package in an organization's SBOM against real deployment signals: build target (prod/test/dev), network exposure (internet-facing vs. internal-only), and data sensitivity tags pulled from service metadata, so a critical CVE in a customer-facing payment service is never scored or queued the same way as an identical CVE in an archived internal tool. For monorepos and polyglot architectures — the exact scenario where tools like Mend.io tend to lose fidelity — Safeguard classifies at the workspace and package level, not just the repository level, so a shared library used by five different services gets five independently contextualized risk assessments instead of one blanket verdict. The result for teams that switch is consistent with the industry patterns above: fewer false-urgent tickets, remediation queues sorted by actual exploitability and exposure rather than raw CVSS, and an audit trail that shows auditors and engineering leadership exactly why each finding was prioritized the way it was. If your current SCA tool is generating hundreds of findings a quarter that all look equally urgent, that's not a sign of a thorough scanner — it's a sign of missing context, and it's precisely the gap Safeguard was built to close.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.