CWE-638, Not Using Complete Mediation, is the failure to check access on a resource every time it is accessed. It is a design principle violation that affects any system where rights can change over time.
How it happens
Teams check permission when a session opens or a handle is created, then reuse the result. That is faster, but rights change. A user is removed from a group, a role is revoked, a certificate expires. The cached decision does not notice.
# Checked once, trusted forever
handle = open_report(user) # permission verified here
while True:
handle.read() # still works after revocation
MITRE's observed example is a server that did not properly validate client certificates when reusing cached connections (CVE-2007-0408).
What an attacker gains
The record lists a wide set of impacts: gaining privileges, bypassing protection mechanisms, reading application data and executing unauthorized code. A user might retain access to a critical resource even after privileges have been revoked.
How to find it
The record lists no detection methods. Look for caches of access decisions, long-lived handles, tokens and descriptors, and ask what invalidates each one when permissions change.
How to fix it
From MITRE:
- Invalidate cached privileges, file handles or descriptors, or other access credentials whenever identities, processes, policies, roles, capabilities or permissions change.
- Perform complete authentication checks before accepting, caching and reusing data, dynamic content and code.
- Avoid caching access control decisions as much as possible.
- Identify all code paths that might access sensitive resources. If possible, create and use a single interface that performs the access checks, and require its use through code standards.
A closer look at caches and long-lived handles
Complete mediation fails most often through performance work. A team notices that permission lookups are slow, adds a cache, and the cache outlives the permission.
Handles and descriptors behave the same way. A file opened while a user had access stays open after the user loses it. A connection reused across requests keeps the identity it was created with. MITRE's example, a server reusing cached connections without properly validating client certificates, follows this pattern.
The mitigation list gives a workable plan. First, list every code path that reaches a sensitive resource. Second, route them all through one access-check interface. Third, hook that interface into your revocation events so that a changed role or policy invalidates what was cached.
If you must cache, keep lifetimes short and tie the cache key to the identity and the policy version, so that a change makes old entries unusable.
Review checklist:
- Which caches hold access decisions, tokens or handles?
- What event invalidates each one?
- Is there one shared function that every path calls before touching the resource?
- Do role, group and policy changes reach those caches right away?
If the answer to the second question is time passing, you have a window in which revoked rights still work.
Quick check
What is the benefit of a single access-check interface?
Every path to the resource goes through the same check, so no path is missed and changes are made in one place.