[ 
https://issues.apache.org/jira/browse/OPENNLP-1902?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Martin Wiesner updated OPENNLP-1902:
------------------------------------
    Component/s: Models

>  DownloadUtil does not re-verify cached models against their SHA-512 checksum
> -----------------------------------------------------------------------------
>
>                 Key: OPENNLP-1902
>                 URL: https://issues.apache.org/jira/browse/OPENNLP-1902
>             Project: OpenNLP
>          Issue Type: Improvement
>          Components: Models
>            Reporter: Richard Zowalla
>            Priority: Major
>             Fix For: 2.5.12, 3.0.0-M6
>
>          Time Spent: 40m
>  Remaining Estimate: 0h
>
> {\{DownloadUtil.downloadModel(URL, Class)}} verifies the SHA-512 checksum 
> only on the
> path where the model is actually fetched. When the model is already present 
> in the
> local download home, the method logs "Model file '{}' already exists. Skipping
> download." and hands the file straight to the model constructor without any
> integrity check:
>     if (!Files.exists(localFile)) {
>       ...
>       Files.copy(in, localFile, StandardCopyOption.REPLACE_EXISTING);
>       validateModel(url + ".sha512", localFile);   // <-- fresh download only
>     } else {
>       logger.debug("Model file '{}' already exists. Skipping download.", 
> filename);
>     }
> The two entry points in this class therefore disagree: \{{existsModel(...)}} 
> *does*
> call \{{validateModel(...)}} for an already-present file, while 
> \{{downloadModel(...)}}
> — the path that actually loads the model — does not.
> Consequence: once a model is in the download home (~/.opennlp by default, 
> overridable
> via the OPENNLP_DOWNLOAD_HOME system property), every subsequent load trusts 
> it
> unconditionally. A model that is corrupted on disk, truncated by an 
> interrupted
> download, or modified by any process with write access to that directory is 
> loaded
> without complaint. This is defense in depth rather than a boundary we 
> guarantee —
> per SECURITY.md, model files are trusted input — but the checksum is already
> published and already fetched, so the check is cheap to get right.
> Note the constraint on the fix: \{{validateModel(String, Path)}} downloads the
> ".sha512" file from the CDN each time it is called. Simply invoking it on the 
> cache
> path would turn every cached load into a network request and break 
> offline/air-gapped
> reuse of the download home, which is a large part of why the cache exists.
> Proposed approach:
>  - Persist the ".sha512" file alongside the model on first download.
>  - On a cache hit, verify the local model against the locally stored 
> checksum, with
>    no network access.
>  - If the stored checksum is missing (cache populated by an older version), 
> either
>    re-download the checksum when the network is reachable or fail closed — to 
> be
>    decided during implementation; a system property to opt out of cache 
> verification
>    may be warranted for constrained environments.
>  - Align \{{existsModel(...)}} and \{{downloadModel(...)}} so both use the 
> same
>    verification routine.
>  - Add tests: valid cached model passes; tampered cached model fails; missing
>    checksum sidecar behaves as decided; no network calls on the cache-hit 
> path.
> Reported by Jeff Zemerick during review of PR #1198 (OPENNLP-1900). The 
> current
> behaviour is documented in SECURITY.md under "Downloaded models"; that note 
> should be
> updated when this is fixed.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to