Skip to content

OPENNLP-1900: Document and publish the OpenNLP security model - #1198

Open
rzo1 wants to merge 2 commits into
mainfrom
OPENNLP-1900
Open

OPENNLP-1900: Document and publish the OpenNLP security model#1198
rzo1 wants to merge 2 commits into
mainfrom
OPENNLP-1900

Conversation

@rzo1

@rzo1 rzo1 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

This adds a SECURITY.md at the repository root and links it from README.md, so
the reporting instructions and the security model live in the same place — as the
ASF guidance
recommends.

This is a first draft and it is meant for discussion. I would rather argue
about the boundaries now, in a PR, than in a triage thread while a reporter waits.

Why now

We have no published security model. There is no SECURITY.md, nothing in
opennlp-docs, and the only written statement about input trust anywhere in the
tree is a javadoc caveat on SvmDoccatModel.deserialize() telling callers to use
trusted streams only.

That gap is getting expensive. The volume of AI-assisted vulnerability reports is
climbing across the ASF, and OpenNLP is an attractive target for them: we
deserialize several independent binary formats, so a model that has learned the
shape of one finding can generate the sibling for every other reader we ship.
Those reports are often technically accurate about the code and completely silent
on the question that actually decides the outcome — is this input attacker-
controlled? Without a written model, every one of them gets relitigated from
scratch, and we answer from memory, inconsistently.

Our own record is genuinely ambiguous on the central question:

  • CVE-2026-42440 — unbounded allocation from a model stream: accepted and fixed.
  • CVE-2026-43825 — unsafe deserialization in SvmDoccatModel: accepted and fixed.
  • OPENNLP-1891BaseModel deserialization hardened with an ObjectInputFilter.
  • OPENNLP-1899 — the same MAX_ENTRIES bound applied to SymSpellModelSerializer.
  • And yet SvmDoccatModel's javadoc says the opposite: trusted streams only.

In practice we behave as though models should be trusted and we harden the readers
anyway. That is a defensible position. It is just not written down anywhere, so it
cannot be cited, and a reporter has no way to know it before spending their time.

What it says

The framing that does most of the work: OpenNLP is a library and a set of CLI
tools. No sockets, no daemons, no accounts, no auth, no web UI. So the model
reduces almost entirely to input trust boundaries, and the whole class of
questions the ASF guidance asks about — admin roles, brute-force protection,
username enumeration — is simply not applicable.

Each input category gets an explicit trust level:

Input Trust level
Text under analysis Untrusted — hostile text must not crash, hang, or blow up memory
Model artifacts, dictionaries Trusted, hardened as defense in depth
Downloaded models Trusted, integrity-checked (SHA-512 over HTTPS)
Training data Trusted
Configuration, system properties Fully trusted
CLI tools As trusted as the invoking user

Plus sections on third-party dependencies (ONNX Runtime is native code we do not
sandbox), logging, seven pre-adjudicated known non-findings, and an explicit
invitation to send hardening reports that fall outside the guarantees.

Everything factual is taken from the code rather than assumed — the SHA-512
verification in DownloadUtil, the secure-processing and no-DOCTYPE settings in
XmlUtil, the ObjectInputFilter allowlists in BaseModel and SvmDoccatModel,
and the MAX_ENTRIES / OPENNLP_MAX_ENTRIES bound in AbstractModelReader.

Please push back on these specifically

  1. The model-file position. I wrote it as no guarantee, real effort, reports
    welcome, CVE where impact warrants
    , citing both CVEs as precedent. This is the
    escape hatch the ASF guidance explicitly offers. The alternative — models are
    trusted, findings get fixed but never get a CVE — is defensible too, but it is
    a deliberate choice and it means reconciling the SvmDoccatModel javadoc.
    Whatever we pick, the next report in this class should be answerable by citing
    a paragraph.
  2. ReDoS listed as in-scope. Catastrophic backtracking on input text is a real
    commitment across every built-in regex in the tokenizers and normalizers. Do we
    want to make it?
  3. Supported versions. I wrote "latest 2.x and current 3.x, 1.x is EOL" from
    the tag history and the CVE-2026-42440 advisory. If there is a stated policy I
    missed, this should match it.
  4. Training data as trusted. Corpus readers in opennlp-formats are not
    written defensively. I think that is the right call for an offline operator
    activity, but it is worth a second opinion.

Follow-up, not in this PR

The website is a separate repository, so opennlp.apache.org still needs a link
to this once it lands.

Related: OPENNLP-1899 (branch OPENNLP-1899) applies the MAX_ENTRIES bound to
SymSpellModelSerializer and is the report that prompted this ticket.

@rzo1 rzo1 self-assigned this Jul 28, 2026
Comment thread SECURITY.md
Comment thread SECURITY.md Outdated
Comment thread SECURITY.md
Comment thread SECURITY.md
- Frame the trust bullets as guidance for the user's own mindset
- Recommend explicitly against loading untrusted models
- Correct the deserialization hardening claim: BaseModel installs an
  allowlist only, the graph depth/reference/array limits are SvmDoccatModel
- Note that checksum verification happens at download time and cached
  models are not re-verified on subsequent loads
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants