This is a mislabeled locker key, not a master key to the building
Tenable plugin 102587 maps to CVE-2017-7674, a Tomcat CORS filter bug fixed in Apache Tomcat 7.0.79. Affected Tomcat 7 versions are 7.0.41 through 7.0.78. The flaw is simple: Tomcat's CorsFilter failed to add a Vary: Origin header, so caches could incorrectly reuse a response generated for one Origin when serving another, enabling *client-side or shared-cache poisoning in some circumstances*.
The vendor's MEDIUM label is technically defensible but operationally still a bit high for most enterprises. This is not pre-auth RCE, not auth bypass, and not a broad server compromise path; exploitation usually requires the app to actually use Tomcat's CorsFilter, to emit cacheable origin-sensitive responses, and to sit behind a browser or intermediary cache that replays the wrong object. In real fleets, those stacked prerequisites crush exposure, so this lands LOW unless you knowingly run cacheable cross-origin APIs behind shared caches or CDNs.
4 steps from start to impact.
Find a Tomcat app that actually uses CorsFilter
org.apache.catalina.filters.CorsFilter enabled on a reachable endpoint. Version alone is not enough; if the filter is never mapped into web.xml or equivalent app config, this CVE is inert.- Unauthenticated network reachability to the web app
- Tomcat version between 7.0.41 and 7.0.78
- Application explicitly uses Tomcat
CorsFilter
- Many Tomcat deployments do not use the built-in CORS filter at all
- Modern apps often terminate CORS at a reverse proxy, API gateway, framework, or CDN instead of Tomcat
- Version scanners like Nessus detect the binary, not whether the vulnerable filter path is live
102587 is version-based and will overstate reachable exposure when CorsFilter is unused. SCA/SBOM tools catch the library version; they do not prove exploitability.Prime a cache with an origin-specific response
Origin header so Tomcat emits origin-sensitive CORS headers without Vary: Origin. A downstream cache or browser cache can then store that response as if it were generally reusable.- Endpoint responses differ by
Originor include origin-specific CORS headers - The response is cacheable by browser, proxy, CDN, or intermediary
- The cache key does not already include
Origin
- A large percentage of sensitive API responses are already marked
Cache-Control: no-storeorprivate - CDNs and reverse proxies are often configured to bypass caching on authenticated/API traffic
- Some intermediaries already vary on
Originor normalize around CORS behavior
Vary: Origin on CORS responses, but generic network scanners usually cannot. Web proxy logs showing unusual Origin header probing are a better signal than host scanning.Wait for a victim or shared path to reuse the poisoned object
Origin. That may happen in the victim's browser cache or in a shared intermediary serving multiple users, causing the wrong CORS metadata or wrong response variant to be delivered.- A second request arrives through the same cache path
- The second request uses a different
Origincontext - The cached object remains fresh long enough to be reused
- Browser-cache-only cases usually reduce blast radius to one user's device
- Shared cache reuse is highly environment-specific and often short-lived
- Any cache invalidation, short TTL, or no-cache policy kills the chain
Origin and Access-Control-Allow-Origin patterns in CDN/proxy traces. Synthetic probes from two origins against the same cache layer are the most reliable validation.Abuse the poisoned response for low-grade integrity impact
- The application relies on origin-sensitive behavior for security or correctness
- Victim-side code meaningfully acts on the poisoned response
- NVD rates confidentiality and availability impact as none, integrity as low
- Many real deployments see nuisance behavior or edge-case policy confusion rather than a durable security break
The supporting signals.
| In-the-wild status | No authoritative evidence of active exploitation found. Not listed in CISA KEV as of 2025-02-14. |
|---|---|
| Proof-of-concept availability | Public write-ups exist for CORS/cache-poisoning technique families, but I found no widely adopted weaponized exploit tied to this Tomcat CVE specifically. This is usually a manual web-app test case, not a commodity exploit. |
| EPSS | FIRST publishes EPSS via its API; third-party mirrors place this CVE in the low single-digit exploit-probability range, which matches the lack of field use. Treat EPSS here as non-driving. |
| KEV status | Not in CISA KEV. That matters: if attackers were getting reliable value from this bug at scale, you'd expect stronger exploitation evidence by now. |
| CVSS vector | CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N (4.3 / MEDIUM). The important parts are UI:R and I:L: it needs a victim/cache interaction and only claims low integrity impact. |
| Affected versions | Tomcat 7.0.41-7.0.78 for this plugin. Broader upstream impact also covered Tomcat 8.0.0.RC1-8.0.44, 8.5.0-8.5.15, and 9.0.0.M1-9.0.0.M21. |
| Fixed versions | Upstream fixed in 7.0.79 for Tomcat 7. Distro backports exist, e.g. Debian tomcat7 7.0.56-3+really7.0.88-1 and Ubuntu Trusty tomcat7 7.0.52-1ubuntu0.13. |
| Scanning / exposure reality | Internet-wide search engines can find Tomcat banners, but they cannot reliably prove this CVE because exploitability depends on app-level CorsFilter usage and cache behavior, not just a banner or version string. |
| Disclosure date | Apache Tomcat says the issue was made public on 2017-08-10; NVD publication followed on 2017-08-10/11 depending on timezone normalization. |
| Research / reporting | Apache attributes the report to Tomcat bug 61101 and states the broader implications were identified by the Apache Tomcat Security Team on 2017-05-16. |
noisgate verdict.
The decisive downgrade factor is that version presence is not exposure: the vulnerable path only exists when the application actually uses Tomcat's CorsFilter *and* serves cacheable origin-sensitive responses through a cache path that will replay them. Without those environmental amplifiers, this is mostly a theoretical or edge-case integrity issue rather than a practical enterprise breach path.
Why this verdict
- Requires more than a version: Tomcat 7.0.41-7.0.78 alone is insufficient; the app must actively use
org.apache.catalina.filters.CorsFilter. - Cache behavior is the real gate: no reusable browser/proxy/CDN cache path, no meaningful exploit chain.
- Impact is narrow by design: upstream/NVD land on low integrity impact with no confidentiality or availability loss, which matches the likely blast radius.
- No field pressure: no KEV entry, no strong public in-the-wild reporting, and no common offensive tooling adoption surfaced.
- Version scanner inflation: Tenable flags binary version, not the presence of origin-sensitive cacheable endpoints, so the reported population will be larger than the truly exploitable population.
Why not higher?
This is not a generic internet RCE, auth bypass, or file-read bug. The chain needs stacked prerequisites: vulnerable Tomcat version, live CorsFilter usage, cacheable origin-varying responses, and a victim or shared cache path that actually reuses the poisoned object. Those are meaningful compounding friction points.
Why not lower?
It is still a real upstream security issue with a published CVE, fix, and plausible abuse path in environments using cross-origin APIs behind shared caches. If you run origin-sensitive APIs through CDNs or reverse proxies and rely on CORS behavior for correctness, the bug can move from theoretical to practical fast enough that IGNORE would be sloppy.
What to do — in priority order.
- Disable caching on CORS-sensitive responses — Set
Cache-Control: no-storeor at minimumprivateon origin-sensitive API responses so the poisonable object never becomes reusable. For a LOW verdict there is no formal mitigation SLA, but if you cannot patch soon and you know these endpoints exist, apply this as backlog hygiene while you work the patch. - Add
Vary: Originat the edge — If you terminate traffic at NGINX, Apache httpd, a load balancer, API gateway, or CDN, injectVary: Originon affected responses there. That breaks the cache-confusion condition even before the Tomcat upgrade; for LOW, do it opportunistically where cross-origin APIs are business-critical. - Inventory actual
CorsFilterusage — Search deployedweb.xmlfiles and app configs fororg.apache.catalina.filters.CorsFilterso you can separate theoretical version hits from real exposure. This should be done during normal backlog cleanup because the reassessed severity does not justify an emergency response. - Prefer non-cacheable auth/API paths at the CDN — Explicitly bypass caching for authenticated or origin-sensitive API routes in CDNs and reverse proxies. This hardens the environment regardless of Tomcat version and is especially useful if Tomcat 7 is embedded in vendor appliances you cannot patch quickly.
- Generic EDR does not help much; the traffic is normal HTTP with
Originheaders, not a payload that spawns a process or drops malware. - A WAF may log odd headers, but it usually will not fix the missing
Vary: Originsemantics or stop cache reuse by itself. - Simply hiding the Tomcat banner does nothing; this CVE is about application CORS/cache behavior, not banner-based exploitation.
Crowdsourced verification payload.
Run this on the target Tomcat host as a local shell user with read access to the Tomcat install and deployed app configs; root is not strictly required unless permissions are locked down. Invoke it as bash verify_tomcat_cve_2017_7674.sh /opt/tomcat or omit the argument to auto-check common paths; it reports VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env bash
# verify_tomcat_cve_2017_7674.sh
# Checks Apache Tomcat 7 for CVE-2017-7674 exposure conditions.
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
TARGET_PATH="${1:-}"
find_tomcat_home() {
if [[ -n "$TARGET_PATH" && -d "$TARGET_PATH" ]]; then
echo "$TARGET_PATH"
return 0
fi
local candidates=(
"$CATALINA_HOME"
"$CATALINA_BASE"
/opt/tomcat
/usr/share/tomcat7
/var/lib/tomcat7
/usr/local/tomcat
/opt/apache-tomcat-7*
)
local c
for c in "${candidates[@]}"; do
[[ -n "${c:-}" ]] || continue
for expanded in $c; do
if [[ -d "$expanded" && ( -f "$expanded/lib/catalina.jar" || -f "$expanded/bin/version.sh" ) ]]; then
echo "$expanded"
return 0
fi
done
done
return 1
}
extract_version() {
local home="$1"
local version=""
if [[ -f "$home/RELEASE-NOTES" ]]; then
version=$(grep -Eo 'Apache Tomcat Version [0-9]+\.[0-9]+\.[0-9]+' "$home/RELEASE-NOTES" 2>/dev/null | head -n1 | awk '{print $4}')
fi
if [[ -z "$version" && -f "$home/bin/version.sh" ]]; then
version=$(grep -Eo 'Server version: Apache Tomcat/[0-9]+\.[0-9]+\.[0-9]+' "$home/bin/version.sh" 2>/dev/null | head -n1 | cut -d/ -f2)
fi
if [[ -z "$version" && -f "$home/lib/catalina.jar" && -x "$(command -v unzip)" ]]; then
version=$(unzip -p "$home/lib/catalina.jar" META-INF/MANIFEST.MF 2>/dev/null | awk -F': ' '/Implementation-Version/ {print $2; exit}' | tr -d '\r')
fi
echo "$version"
}
ver_to_int() {
local IFS=.
local a b c
read -r a b c <<< "$1"
a=${a:-0}; b=${b:-0}; c=${c:-0}
printf '%03d%03d%03d\n' "$a" "$b" "$c"
}
is_vulnerable_version() {
local v="$1"
[[ "$v" =~ ^7\.[0-9]+\.[0-9]+$ ]] || return 1
local vi
vi=$(ver_to_int "$v")
local low high
low=$(ver_to_int "7.0.41")
high=$(ver_to_int "7.0.79")
[[ "$vi" -ge "$low" && "$vi" -lt "$high" ]]
}
check_cors_filter_usage() {
local home="$1"
local found=1
local paths=(
"$home/conf/web.xml"
"$home/webapps"
"$home/conf/Catalina"
)
local p
for p in "${paths[@]}"; do
[[ -e "$p" ]] || continue
if grep -RIsq 'org\.apache\.catalina\.filters\.CorsFilter\|<filter-class>.*CorsFilter</filter-class>' "$p" 2>/dev/null; then
found=0
break
fi
done
return $found
}
HOME_DIR=$(find_tomcat_home) || {
echo "UNKNOWN - could not locate Tomcat home"
exit 2
}
VERSION=$(extract_version "$HOME_DIR")
if [[ -z "$VERSION" ]]; then
echo "UNKNOWN - could not determine Tomcat version under $HOME_DIR"
exit 2
fi
if ! [[ "$VERSION" =~ ^7\.[0-9]+\.[0-9]+$ ]]; then
echo "PATCHED - Tomcat version $VERSION is outside the Tomcat 7 vulnerable range checked by this script"
exit 0
fi
if is_vulnerable_version "$VERSION"; then
if check_cors_filter_usage "$HOME_DIR"; then
echo "VULNERABLE - Tomcat $VERSION with CorsFilter usage detected under $HOME_DIR"
exit 1
else
echo "PATCHED - Tomcat $VERSION is in the affected version band, but no CorsFilter usage was detected; CVE-2017-7674 path not evidenced"
exit 0
fi
else
echo "PATCHED - Tomcat version $VERSION is not in 7.0.41-7.0.78"
exit 0
fi
If you remember one thing.
CorsFilter and sit behind a cacheable cross-origin path; if you find those, add Vary: Origin or disable caching on those routes as backlog hardening. For a LOW reassessment there is no noisgate mitigation SLA and noisgate remediation SLA is no SLA (treat as backlog hygiene), so roll the actual Tomcat fix into normal maintenance rather than emergency change control—but if the host is still on Tomcat 7, treat the larger issue as EOL platform retirement, because this CVE is not the worst thing about that stack.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.