← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2025-0227 · CWE-200 · Disclosed 2025-01-05

A vulnerability

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a misplaced office key behind the receptionist desk, not a front-door master key

CVE-2025-0227 is a remote file disclosure bug in Tsinghua Unigroup Electronic Archives System affecting version 3.2.210802(62532). The vulnerable component is the /Logs/Annals/downLoad.html handler, where a user-controlled path argument can be manipulated to retrieve unintended files readable by the application, yielding confidentiality impact without stated integrity or availability impact.

The vendor's MEDIUM 4.3 baseline is already restrained, and in enterprise reality it trends slightly lower. The decisive friction is PR:L: the attacker must already hold a valid low-privilege account or equivalent session, which makes this mostly a post-initial-access or post-credential-theft problem in a niche product with no KEV listing, very low EPSS, no public evidence of broad exploitation, and only partial impact.

"Remote, but only after login and only for low-grade file disclosure in a niche app."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Land a valid application session

The attacker first needs a legitimate low-privilege login to the archives system, or a stolen session cookie. Tooling here is boring: browser login, credential stuffing against exposed auth, or reuse of a session token from prior compromise. This is the biggest severity brake because it is not an unauthenticated edge exploit.
Conditions required:
  • Network reachability to the application
  • A valid low-privilege user account or reusable authenticated session
  • The target runs the affected 3.2.210802(62532) build
Where this breaks in practice:
  • MFA, SSO, or VPN gating can materially reduce reachable population
  • Many deployments of this product are likely internal-only, not internet-facing
  • Without credentials, the CVSS PR:L prerequisite blocks first-hop abuse
Detection/coverage: Identity telemetry, SSO logs, and failed-login analytics should see the account acquisition phase; generic vulnerability scanners often miss auth-gated bugs unless supplied valid credentials.
STEP 02

Probe the vulnerable download handler

Using Burp Suite, curl, or the PoC path referenced in the CVE record, the attacker sends requests to /Logs/Annals/downLoad.html while tampering with the path parameter. The goal is to coerce the handler into returning a file outside the intended access scope.
Conditions required:
  • Authenticated access to the application
  • The vulnerable endpoint is deployed and reachable
  • Request parameter handling is unchanged from the affected release
Where this breaks in practice:
  • Endpoint paths can vary across reverse proxies or customized deployments
  • WAF or reverse-proxy normalization may block obvious traversal-style payloads
  • Some deployments may remove or restrict the module entirely
Detection/coverage: Good web logs can catch repeated requests to downLoad.html with anomalous path values; off-the-shelf external scanners have weak coverage unless they understand the app and authenticate.
STEP 03

Read files the app account can access

If exploitation succeeds, the server returns file content that the application process can read. In practice that usually means configuration files, document metadata, local logs, or stored records within the app's permission boundary rather than full host compromise.
Conditions required:
  • The server-side process has read access to useful files
  • Requested files are not separately access-controlled by the application
  • Returned content is not redacted or blocked by the server
Where this breaks in practice:
  • The impact is capped at confidentiality and only what the app account can read
  • OS permissions and containerization can sharply limit what is obtainable
  • There is no stated write, code execution, or service-crash path
Detection/coverage: Application access logs, unusual file-download volume, and proxy telemetry may show anomalous reads; EDR is unlikely to help much if the app reads files through normal process behavior.
STEP 04

Use disclosed data for follow-on abuse

The attacker may use exposed records, config secrets, or internal paths to support lateral phishing, further credential theft, or chained attacks. This is where the business risk lives, but it is contingent on what files are actually exposed and how sensitive they are.
Conditions required:
  • The disclosed files contain sensitive data or reusable secrets
  • The attacker can operationalize the information elsewhere
Where this breaks in practice:
  • Many accessible files may be low-value operational artifacts
  • No direct integrity or availability impact is built into this CVE
  • Blast radius is usually limited to one application dataset or host context
Detection/coverage: Downstream misuse shows up in DLP, IAM, and data-access monitoring more than in classic exploit detection.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo reliable public evidence of active exploitation found in the sources reviewed; CISA ADP SSVC marks Exploitation: none.
Proof-of-concept availabilityThe CVE record references a public GitHub PoC at BxYQ/ld/file_read1/poc.py; the original repo path appears unavailable now, but the CVE/OpenCVE record still documents it as public exploit material.
EPSS0.00123 from your intel block, which is extremely low and consistent with a niche, auth-required issue.
KEV statusNo as of this assessment; not present in the CISA KEV catalog.
CVSS vector reality checkCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N maps to *remote but authenticated* with *low confidentiality-only* impact. That is a built-in downward pressure compared with unauthenticated edge bugs.
Affected versionsCVE/OpenCVE lists Tsinghua Unigroup Electronic Archives System 3.2.210802(62532) as affected. No broader version range was published in the record I reviewed.
Fixed versionNo vendor-fixed version or workaround was published in the cited record; treat patched_version as unknown and verify with the vendor or maintainer.
Disclosure timelineReserved 2025-01-04, published 2025-01-05, and CISA ADP enrichment updated 2025-01-06.
Reporter / assigning authorityAssigned by VulDB per the CVE metadata surfaced in OpenCVE.
Exposure / scanning dataI found no trustworthy public Shodan/Censys/FOFA count for this specific product+endpoint combination in the reviewed sources. That absence itself argues against assuming broad internet exposure.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.2/10)

The single most important reason this lands in LOW is the PR:L requirement: an attacker must already be authenticated, which makes this a follow-on weakness rather than a clean initial-access path. The impact is also bounded to low confidentiality loss with no published integrity, availability, or code-execution angle.

HIGH Auth requirement materially suppresses internet-scale risk
MEDIUM Impact ceiling is low confidentiality-only based on available public detail
LOW Exact fixed version information is unavailable in public sources reviewed

Why this verdict

  • Requires authenticated remote access: PR:L means the attacker needs a valid user account or stolen session first, which implies prior compromise, insider access, or successful credential abuse.
  • Narrow blast radius: the published impact is file disclosure within the application's readable scope, not host takeover, not arbitrary write, and not service outage.
  • Low public threat signal: no KEV listing, extremely low EPSS, and no solid evidence of active campaigns reduce urgency despite the PoC reference.
  • Likely niche exposure population: this is not a commodity internet edge product with massive U.S. enterprise footprint, so the vendor score slightly overstates typical fleet-wide urgency for a 10,000-host program.

Why not higher?

This is not an unauthenticated edge compromise and there is no published RCE, auth bypass, mass exploitation evidence, or destructive outcome. Even if reachable over the network, the attacker must already be inside the trust boundary of the application and the documented effect is only low confidentiality loss.

Why not lower?

It is still a real remote application flaw with a disclosed exploit reference, and once an attacker has credentials the path to abuse is straightforward. Archives platforms often hold sensitive documents, so even a low-impact disclosure bug can matter if this app stores HR, legal, or regulated records.

05 · Compensating Control

What to do — in priority order.

  1. Force the app behind trusted access paths — If this system is internet-exposed, move it behind VPN, ZTNA, or source-IP restrictions so the PR:L prerequisite cannot be exercised from the open internet. For a LOW verdict there is no formal SLA; treat this as backlog hygiene and complete it in normal hardening work if exposure exists.
  2. Tighten low-privilege account hygiene — Review dormant users, weak local passwords, and shared service accounts because this CVE only matters after authentication. For LOW, there is no mitigation SLA; fold this into routine IAM cleanup and prioritize any account class that can sign into the archives app.
  3. Log and alert on anomalous downLoad.html access — Add reverse-proxy or application logging for repeated requests to /Logs/Annals/downLoad.html with unusual path values, then alert on spikes or off-hours access. For LOW, deploy as backlog hygiene rather than emergency change, unless the system holds highly sensitive records.
  4. Restrict filesystem readability of the app account — Constrain the service account and webroot so successful abuse exposes as little as possible beyond intended archives content. There is no SLA for LOW, but this is one of the few controls that directly shrinks the blast radius even before a vendor patch exists.
What doesn't work
  • EDR alone does not solve this because the application can read files through normal process behavior; nothing about a successful read necessarily looks malicious at the OS level.
  • Network segmentation by itself is weak if the attacker already has internal access or a valid app session; the bug lives in the authenticated web workflow.
  • Password rotation without MFA or session controls is incomplete if session cookies can be stolen or reused.
06 · Verification

Crowdsourced verification payload.

Run this on the application server or on a mounted application image, not from a random auditor workstation, because it performs an offline install check rather than active exploitation. Invoke it with python3 check_cve_2025_0227.py --root /opt/earchives and supply read access to the installation directory; no admin rights are required beyond filesystem read permissions.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# check_cve_2025_0227.py
# Offline checker for CVE-2025-0227 in Tsinghua Unigroup Electronic Archives System
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=usage/runtime error

import argparse
import os
import re
import sys
from pathlib import Path

AFFECTED_VERSION = "3.2.210802(62532)"
ENDPOINT_SUFFIX = Path("Logs") / "Annals" / "downLoad.html"
PRODUCT_HINTS = [
    "Electronic Archives System",
    "Tsinghua Unigroup",
    "Archives",
    "电子档案",
]
VERSION_FILE_CANDIDATES = [
    "version.txt",
    "VERSION",
    "build.txt",
    "manifest.mf",
    "pom.properties",
    "application.properties",
]
MAX_SCAN_FILES = 4000
MAX_READ_BYTES = 2 * 1024 * 1024


def read_text_safely(path: Path):
    try:
        if path.stat().st_size > MAX_READ_BYTES:
            return None
        return path.read_text(encoding="utf-8", errors="ignore")
    except Exception:
        return None


def find_endpoint(root: Path):
    matches = []
    for p in root.rglob("downLoad.html"):
        try:
            rel = p.relative_to(root)
        except Exception:
            rel = p
        if str(rel).replace('\\', '/').endswith(str(ENDPOINT_SUFFIX).replace('\\', '/')):
            matches.append(p)
    return matches


def scan_for_version_and_product(root: Path):
    version_match = False
    product_hint = False
    scanned = 0

    preferred = []
    for name in VERSION_FILE_CANDIDATES:
        preferred.extend(root.rglob(name))

    seen = set()
    ordered_paths = []
    for p in preferred:
        if p.is_file() and p not in seen:
            ordered_paths.append(p)
            seen.add(p)

    for p in root.rglob("*"):
        if scanned >= MAX_SCAN_FILES:
            break
        if p.is_file() and p not in seen:
            ordered_paths.append(p)
            seen.add(p)
        scanned += 1

    for p in ordered_paths:
        text = read_text_safely(p)
        if not text:
            continue
        if AFFECTED_VERSION in text:
            version_match = True
        for hint in PRODUCT_HINTS:
            if hint.lower() in text.lower():
                product_hint = True
                break
        if version_match and product_hint:
            break

    return version_match, product_hint


def main():
    parser = argparse.ArgumentParser(description="Offline check for CVE-2025-0227")
    parser.add_argument("--root", required=True, help="Application installation root")
    args = parser.parse_args()

    root = Path(args.root)
    if not root.exists() or not root.is_dir():
        print("UNKNOWN - installation root not found or not a directory")
        return 2

    endpoint_hits = find_endpoint(root)
    version_match, product_hint = scan_for_version_and_product(root)

    if endpoint_hits and version_match:
        print("VULNERABLE - found affected version '{}' and endpoint '{}'".format(
            AFFECTED_VERSION, ENDPOINT_SUFFIX.as_posix()
        ))
        return 1

    if product_hint and not endpoint_hits:
        print("PATCHED - product indicators found but vulnerable endpoint '{}' not present".format(
            ENDPOINT_SUFFIX.as_posix()
        ))
        return 0

    if endpoint_hits and not version_match:
        print("UNKNOWN - vulnerable endpoint exists but affected version string '{}' was not confirmed".format(
            AFFECTED_VERSION
        ))
        return 2

    if version_match and not endpoint_hits:
        print("UNKNOWN - affected version string found but endpoint '{}' was not located".format(
            ENDPOINT_SUFFIX.as_posix()
        ))
        return 2

    print("UNKNOWN - insufficient evidence to confirm product, version, or endpoint")
    return 2


if __name__ == "__main__":
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        print("UNKNOWN - interrupted")
        sys.exit(2)
    except Exception as exc:
        print(f"UNKNOWN - runtime error: {exc}")
        sys.exit(3)
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, find every deployment of this archives platform, confirm whether any instance is internet-reachable, and verify whether the installed build matches 3.2.210802(62532). Because this is LOW, there is no noisgate mitigation SLA and no noisgate remediation SLA—treat it as backlog hygiene, document the auth-required exposure, restrict access if any instance is externally reachable, and track the vendor for a real fixed version before folding remediation into routine maintenance.

Sources

  1. OpenCVE record for CVE-2025-0227
  2. CVEFeed detail page
  3. Feedly CVE page
  4. Singapore CSA Security Bulletin 08 January 2025 PDF
  5. CISA Vulnerability Summary SB25-006
  6. CISA Known Exploited Vulnerabilities Catalog
  7. FIRST EPSS overview
  8. VulDB reference from the CVE record
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.