Load Path Research The mechanism you have vs the property you need

Layer conflation

A shared top-ten category is not a shared root cause.

A Shared Top-Ten List Is Not a Shared Root Cause

CWE places each weakness at an abstraction level and regroups the same entries into audience-specific views, while application security's mechanism analysis shows injection, insecure deserialization and SSRF sharing one boundary violation that authorization flaws do not share; where they touch, grouping findings by a common Pillar, view or top-ten list looks like root-cause analysis without being it, and remediation has to follow the mechanism rather than the bucket.

“Most of our findings are injection and access-control bugs, so they are all input-validation problems, and one validation library will fix them.”

Let me stop you before that becomes a procurement request.

A shared top-ten category is not a shared root cause.

A list tells you where a finding is filed.

A root cause tells you what actually failed.

Sometimes those line up.

In this sentence, they don’t.

Injection, insecure deserialization and SSRF genuinely share one mechanism.

Broken object authorization does not share it, however often it appears on the same slide.

And a validation library, whatever else it does, cannot install a permission decision that nobody wrote.

This isn’t pedantry about taxonomy.

It is the difference between a fix that closes a class of findings and a fix that closes half of them while the other half keeps shipping.

So separate the bucket from the mechanism, one objection at a time.

1. “But They Are All on the Same OWASP List.”

They are.

A list is a filing decision.

It is not a diagnosis.

Start with what the three injection-shaped classes actually share, stated precisely.

Data that originated outside the application’s trust boundary is passed into a context that interprets it as instructions, without the crossing being checked.

That is the whole event.

What changes is which interpreter sits on the far side.

In SQL injection, CWE-89, it is the database engine. A search term stops being an argument and becomes part of the query’s structure. ' OR '1'='1 stops being a string and becomes a clause.

In insecure deserialization, CWE-502, it is the runtime’s own object-reconstruction machinery. Java’s ObjectInputStream. Python’s pickle. PHP’s unserialize(). A mechanism whose entire job is to build objects and invoke their methods, handed bytes an attacker controls.

In SSRF, CWE-918, it is the application’s own HTTP or socket client. A webhook target, an image-fetch endpoint, an XML external entity, dereferenced by server code that trusts the destination the way it would trust a hardcoded internal address.

Three engines.

One precondition.

The missing check is not “was this data present”.

It is “does this data, in the place it is about to go, still mean only data”.

Now put a broken object-level authorization finding beside them.

The record identifier in the request is interpreted exactly as what it is.

A record identifier.

No parser was confused. No interpreter was hijacked. Nothing crossed from data into instructions.

A request asked for a record, and nobody asked whether this caller may have it.

That is a permissions problem, not an interpretation problem.

Both belong on a list of things that go wrong in web applications.

So do stairs and electrical faults on a list of household injuries.

Nobody fixes the wiring with a handrail.

2. “But CWE Files Them All Under Improper Access Control or Improper Neutralization Anyway.”

CWE files things in more than one way, and that is exactly the point.

Every CWE weakness entry sits at one of four abstraction levels.

Pillar. The most abstract, naming a theme rather than a mechanism. CWE-284, Improper Access Control, is one.

Class. Technology-independent, a general pattern in one or two dimensions.

Base. Specific enough, typically two to three dimensions, to support concrete detection and prevention advice. CWE-79 and CWE-89 are Base entries.

Variant. Tied to a technology or language family, across three to five dimensions. CWE-416, Use After Free, is a Variant scoped to memory-unsafe languages, under the Base entry CWE-825, Expired Pointer Dereference.

The level is the unit of how specific the claim is.

Walk the injection side down.

CWE-89 is a child of CWE-943, Improper Neutralization of Special Elements in Data Query Logic.

CWE-943 also parents LDAP Injection, CWE-90, and XML Query Injection, CWE-652.

Sideways, OS Command Injection, CWE-78, and general Command Injection, CWE-77, share the identical root pattern with a different interpreter: shell, or generic command processor, instead of SQL engine.

CWE-79 sits under CWE-74, Improper Neutralization of Special Elements in Output Used by a Downstream Component, with Variant children that split XSS by injection context.

Now walk the access-control side.

IDOR and broken object-level authorization sit under the CWE-284 Pillar.

That Pillar is a real relationship.

It is also the most abstract statement CWE can make about a weakness.

Filing a SQL injection and an IDOR together because both are “improper something” at the top of their branches is like concluding two bridges failed the same way because both are in the category “bridges”.

The Pillar tells you which branch of the tree you are in. The Base entry tells you what broke.

There is also a mapping rule that should end the argument.

CWE’s Vulnerability Mapping Notes field marks each entry Allowed, Discouraged or Prohibited for mapping a real vulnerability.

Categories and Views are Prohibited, because they describe organisational structure rather than a root cause.

Some Class entries are Discouraged, because they are too vague to be a useful primary mapping.

The taxonomy itself says the high branches are not where you record why something failed.

3. “But Access-Control Bugs Are Also Caused by Bad Input, Like a Tampered ID.”

Look at the tampered ID.

It is usually a perfectly well-formed identifier.

Correct type. Correct length. Correct format.

It is simply somebody else’s.

Run it through the strictest validation library you can buy. It passes, because nothing about its shape is wrong.

Validation checks what the input is. Authorization checks who may use it.

The injection fix enforces a boundary between data and instructions.

The IDOR fix enforces a boundary between one user’s data and another’s.

Both are boundaries.

They are not the same boundary, and no amount of work on the first installs the second.

CWE-639, Authorization Bypass Through User-Controlled Key, names the pattern for exactly that reason: the key is user-controlled, and the bypass is the absent decision, not a malformed key.

Even on the injection side, “input validation” is too generic to be the root cause.

It does not explain why parameterized queries close SQL injection categorically while string filters only reduce it: the query plan is fixed before the untrusted value is substituted, so no value can alter the plan.

The durable fix in every one of the three classes has that shape.

Move the check to a place where the interpreter structurally cannot do anything else.

A library that inspects strings more carefully is still betting on vigilance.

4. “But an Authorization Check Exists on That Route, So It Cannot Be Missing Authorization.”

Then you may have the other one.

Under CWE-285, Improper Authorization, which itself sits under the CWE-284 Pillar, CWE separates two siblings.

CWE-862, Missing Authorization, is a Class-level entry: no authorization check runs at all before an actor reaches a resource or performs an action.

CWE-863, Incorrect Authorization, covers a check that runs and reaches the wrong answer.

An off-by-one role comparison.

A check against the wrong tenant ID.

Same downstream impact. Different root cause. Different review.

CWE-862 is a code-review finding. You look for the call that isn’t there.

CWE-863 is a logic-review finding. The call exists, and the bug is in its condition.

That distinction is precisely what a Pillar-level bucket erases.

“Access control” holds both.

A team that reads the bucket and adds a check has fixed one of them.

A team that reads the bucket and says “there’s already a check” has closed the ticket on the other.

Neither conversation mentioned input validation, because neither bug involves an interpreter misreading anything.

5. “But CSRF and SSRF Are the Same Kind of Forgery.”

They share a word.

That is the entire relationship.

CWE-352, Cross-Site Request Forgery, forges a request that the victim’s browser sends without the victim knowing. It exploits ambient authentication: the browser attaches the user’s credentials to a request the user never meant to make.

CWE-918, Server-Side Request Forgery, makes the server itself the unwitting requester. It retrieves a URL supplied by an upstream component without confirming the request targets an expected destination, and becomes a proxy into internal networks, cloud metadata endpoints or firewalled services.

One is a browser being borrowed.

The other is a server being steered.

SSRF belongs with injection and deserialization, because a destination supplied as data is being treated as an instruction about where to go.

CSRF does not.

The same name-driven confusion runs next door: CWE-79 and CWE-352 both carry “cross-site” and nothing else in common. XSS injects attacker content into a page the victim views. CSRF forges a request.

If two findings are grouped because their names rhyme, the grouping is a spelling exercise.

Keep them apart in reports.

Keep them apart in training.

Or the next engineer who hears “we fixed forgery” will assume both are covered.

6. “But the Scanner’s Category View Is What Management Reads.”

Fine.

Let management read a view.

Just know what a view is.

CWE version 4.20 carries 944 weakness, category and view entries.

The same underlying entries are regrouped for different audiences, and an entry does not become a different entry when it moves between views.

Research Concepts, CWE-1000, is the abstraction hierarchy as a browsable tree, organised by what mistake was made.

Software Development, CWE-699, regroups the same Base and Variant weaknesses into buckets a developer recognises: API/Function Errors, Authentication Errors, Authorization Errors, Bad Coding Practices, Business Logic Errors. It is a graph, not a tree, so one weakness can appear under more than one bucket.

Hardware Design, CWE-1194, does the same for silicon, with functional categories such as Security Flow Issues and Debug and Test Problems.

And CWE-1344, Weaknesses in OWASP Top Ten (2021), files CWE entries under ten child categories: CWE-1347 for A03:2021 Injection, CWE-1349 for A05:2021 Security Misconfiguration, CWE-1352 for A06:2021 Vulnerable and Outdated Components, and seven siblings.

CWE-79 is a Base weakness in the Research view.

It is a member of the OWASP A03:2021 Injection category.

Not two CWE-79s.

One entry, filed twice, for two audiences.

That is also why a view is the wrong place to choose a fix. Views are built from Categories, a structural type that is not a rung on the Pillar-to-Variant ladder at all.

A view answers “who is reading this”. It does not answer “what failed”.

The part of a CWE entry aimed at the person doing the fixing is lower down the page.

Potential Mitigations is tagged by lifecycle phase: Architecture and Design, Implementation, Build and Compilation, Testing.

Detection Methods names which analysis actually finds instances.

For CWE-125, Out-of-bounds Read, the mitigations include compile-time bounds-checked language features, input validation before array access, and dynamic tools such as AddressSanitizer at the testing phase. Fuzzing and static analysis are rated highly effective at detection; dynamic analysis with sanitizer instrumentation, moderately so.

Related Attack Patterns links outward to CAPEC. CWE-89 links to CAPEC-66, SQL Injection, and CAPEC-66 lists CWE-89 and CWE-1286, Improper Validation of Syntactic Correctness of Input, as the weaknesses it exploits.

That is a remediation-grade record.

It lives on the Base entry, not on the bucket.

Management can read the category chart.

Engineering has to work from the entry.

7. No, This Does Not Mean Grouping Is Useless.

It isn’t.

CWE-699 exists so that secure-code training is organised the way developers think about their own code.

CWE-1344 exists so that an organisation reporting against the OWASP Top Ten can say which weaknesses sit behind each category.

A Pillar is a real relationship in the hierarchy, not decoration.

And some groupings are mechanistically sound. SQL injection, deserialization and SSRF belong together, because they share a boundary violation and a fix of the same shape.

CWE also records when two weaknesses are genuinely linked, and it has names for it.

A Chain links a primary weakness to a resultant one it directly enables.

A Composite requires two or more distinct weaknesses to coexist before the vulnerability exists at all, so removing any one of them closes the hole.

Those are root-cause relationships.

They are stated between specific entries, with evidence.

A bucket describes where a finding is filed. The fix has to come from the mechanism the finding actually has.

Use buckets to count.

Use mechanisms to repair.

8. What You Should Actually Do

Record each finding at the Base or Variant level where the evidence supports it. CWE-89, not “injection”. CWE-862 or CWE-863, not “access control”. A Pillar-level record is a statement that nobody has diagnosed the finding yet.

For each class, write down the mechanism in one line. For an injection-shaped finding: which interpreter sits across the boundary. SQL engine, deserializer, HTTP client, shell. For an authorization finding: which permission decision is missing, or which condition is wrong.

If you cannot fill that line in, you do not yet have a root cause.

Route authorization findings by what the reviewer has to look for. CWE-862 goes to code review for the absent check. CWE-863 goes to logic review of the existing condition.

Fix the injection family structurally, not by vigilance. Where the interpreter can be made incapable of treating data as instructions, do that, and treat string filtering as a fallback rather than a design.

Take mitigations and test methods from the entry itself. Read its phase-tagged Potential Mitigations and its Detection Methods, and check the live page, because not every entry populates every field and the content is revised across list versions.

Keep CSRF, CWE-352, and SSRF, CWE-918, separate in reports, dashboards and training material.

Date the taxonomy. Version 4.20 and 944 entries describe the list today. View contents and entry counts drift with each release, and a report that does not say which version it used cannot be checked later.

Let the category view go upward, and the entry go to the engineer. Both can come from the same finding.

They should not be the same document.

9. The Model Is Not Complicated.

A list asks: which risk category does this belong to?

A root cause asks: what, precisely, failed?

Injection, deserialization and SSRF answer the second question the same way.

Data crossed a trust boundary and something on the far side treated it as instructions.

Broken object authorization answers it differently.

Data was read correctly, and nobody decided whether the caller was allowed to have it.

A top-ten list is not a mechanism. A Pillar is not a diagnosis. A validation library is not an authorization check. And a forged request from a browser is not a forged request from your server.

That is not an argument against classification.

It is an argument for reading it at the level where the fix lives.

Objections

  1. SQL injection, insecure deserialization and SSRF are the same event: data from outside the trust boundary reaches a context that interprets it as instructions, whether a SQL engine, a runtime's object-reconstruction machinery or an HTTP client.
  2. IDOR and broken object-level authorization sit under the CWE-284 Improper Access Control Pillar and are grouped with injection in casual usage because both appear on the OWASP Top 10, but they are missing checks on data interpreted correctly: a permissions problem, not an interpretation problem.
  3. CWE-862 Missing Authorization is a code-review finding, because no check runs, while CWE-863 Incorrect Authorization is a logic-review finding, because a check runs and reaches the wrong answer; both sit under CWE-285.
  4. Every CWE weakness entry has one abstraction level (Pillar, Class, Base or Variant), and the same entry can appear in several Views, such as Research Concepts (CWE-1000), Software Development (CWE-699) and the OWASP Top Ten 2021 mapping (CWE-1344), without becoming a different entry.
  5. A CWE entry's Potential Mitigations are tagged by lifecycle phase and its Detection Methods name which analysis finds instances; for CWE-125, fuzzing and static analysis are rated highly effective.

What this does not say

What this does not mean is that grouping is useless; views such as CWE-699 exist to organise training and reporting, and a Pillar is a real relationship. It means a bucket describes where a finding is filed, and the fix has to be chosen from the mechanism the finding actually has.

Raised in review

What do SQL injection, insecure deserialization and SSRF have in common?
All three are the same event: data that originated outside the application's trust boundary reaches a context that interprets it as instructions, without the crossing being checked. In SQL injection (CWE-89) the interpreter is the database engine. In insecure deserialization (CWE-502) it is the runtime's object-reconstruction machinery. In SSRF (CWE-918) it is the application's own HTTP or socket client.
Why is broken object authorization not an injection problem?
An IDOR is not untrusted data being interpreted as code. The record identifier is interpreted exactly as what it claims to be, and nobody checks whether the requester may hold it. Injection is fixed by enforcing a boundary between data and instructions; IDOR is fixed by enforcing a boundary between one user's data and another's. One is an interpretation problem, the other a permissions problem.
Does sharing an OWASP Top 10 list mean two findings share a cause?
No. The OWASP Top 10 is a set of risk categories, and CWE's own OWASP view, CWE-1344, files CWE entries under ten child categories such as CWE-1347 for A03:2021 Injection. Appearing on the same list says both classes matter. It says nothing about whether they fail through the same mechanism or respond to the same fix.
What are CWE abstraction levels?
Every CWE weakness entry sits at one of four levels: Pillar, Class, Base or Variant. A Pillar names a theme, such as CWE-284 Improper Access Control. A Class names a technology-independent pattern. A Base, such as CWE-89 or CWE-79, is specific enough for concrete detection and prevention advice. A Variant, such as CWE-416 Use After Free, is tied to a technology or language family.
Can one CWE entry appear in several views?
Yes. The same entry can sit in Research Concepts (CWE-1000), Software Development (CWE-699) and the OWASP Top Ten 2021 view (CWE-1344) at once. CWE-79 is a Base weakness in the Research view and a member of the OWASP A03:2021 Injection category. These are not three different entries. A view regroups the same weakness for a different audience without changing its mechanism.
What is the difference between CWE-862 and CWE-863?
CWE-862 Missing Authorization means no authorization check runs before an actor reaches a resource or action. CWE-863 Incorrect Authorization means a check runs and reaches the wrong answer, such as a role comparison off by one or a check against the wrong tenant ID. Both sit under CWE-285 Improper Authorization. The first is found in code review, the second in logic review of the condition.
Are CSRF and SSRF the same kind of forgery?
No. CSRF (CWE-352) forges a request that the victim's browser sends without the victim knowing, exploiting ambient authentication. SSRF (CWE-918) makes the server itself the unwitting requester, fetching a URL supplied by an upstream component without confirming it targets an expected destination. The word forgery is the only thing they share, and it is the whole source of the confusion.
Is a tampered ID in a request an input-validation failure?
Only in the loosest sense. A tampered record ID is usually a perfectly well-formed identifier, so a check on its type, length or format passes it. The failure is that nobody verifies the requester may access that record. Validating the shape of the input does not supply the missing permission decision, which is why a validation library does not close authorization findings.
Why is 'input validation' too broad as a root cause for injection?
It does not explain why structural fixes work where filtering does not. Parameterized queries close SQL injection categorically because the query plan is fixed before the untrusted value is substituted, so no value can change it. A runtime string filter can be evaded by a clever enough payload. The useful root cause names the interpreter across the boundary and how the crossing is enforced.
Where does a CWE entry say how to fix and find a weakness?
In two fields. Potential Mitigations is a list tagged by lifecycle phase, such as Architecture and Design, Implementation, Build and Compilation and Testing. Detection Methods names which analysis techniques find instances. For CWE-125 Out-of-bounds Read, fuzzing and static analysis are rated highly effective and dynamic analysis with sanitizer instrumentation moderately effective.
Should findings be recorded at the Pillar or the Base level?
At the Base or Variant level wherever the evidence supports it. A Base entry is specific enough to carry concrete detection and prevention advice, and a Variant names the technology. A Pillar such as CWE-284 covers both a missing check and a wrong one, which need different reviews. CWE's Vulnerability Mapping Notes mark some Class entries Discouraged as primary mappings because they are too vague.
Why does the same boundary violation keep recurring in new code?
The unsafe version is less effort and runs correctly on every input an engineer tests. Concatenating a query string is shorter than parameterizing it; calling a native deserializer is shorter than writing a schema-constrained parser; fetching any customer-configured webhook URL is the whole point of the feature. The violation only shows when an adversarial input arrives, which ordinary development testing never supplies.