From 855997d91adf1b0184b724980ba6f187a48946c2 Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Thu, 29 Oct 2026 11:50:01 +0100 Subject: [PATCH] Document the Commons Codec threat model --- SECURITY.md | 5 + src/site/markdown/threat-model-1.23.0.md | 196 ++++++++++++++++++ .../markdown/threat-model-short-1.23.0.md | 108 ++++++++++ src/site/site.xml | 7 +- src/site/xdoc/security.xml | 9 +- 5 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 src/site/markdown/threat-model-1.23.0.md create mode 100644 src/site/markdown/threat-model-short-1.23.0.md diff --git a/SECURITY.md b/SECURITY.md index 744d4cddbb..6621e2dee3 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -15,3 +15,8 @@ limitations under the License. --> The Apache Commons security page is [https://commons.apache.org/security.html](https://commons.apache.org/security.html). + +The [Apache Commons Codec Threat Model](src/site/markdown/threat-model-1.23.0.md) +applies to Commons Codec 1.23.0 and later. A +[short summary for developers](src/site/markdown/threat-model-short-1.23.0.md) +is also available. diff --git a/src/site/markdown/threat-model-1.23.0.md b/src/site/markdown/threat-model-1.23.0.md new file mode 100644 index 0000000000..091d5a2a78 --- /dev/null +++ b/src/site/markdown/threat-model-1.23.0.md @@ -0,0 +1,196 @@ + +# Apache Commons Codec Threat Model version 1.23.0 + +This page applies the +[Apache Commons Threat Model 0.1.0](https://commons.apache.org/threat-model-0.1.0.html) +([Markdown](https://svn.apache.org/repos/asf/commons/cms-site/trunk/content/markdown/threat-model-0.1.0.md)) +to Commons Codec. +The family model applies in full; +this page lists only the Codec profile and the points where Codec differs or adds detail. + +This model applies to Commons Codec 1.23.0 and later. +A [short version](threat-model-short-1.23.0.html) +([Markdown](https://raw.githubusercontent.com/apache/commons-codec/master/src/site/markdown/threat-model-short-1.23.0.md)) +is available for developers; +this page is authoritative where the two differ. + +## Profile + +- **Kind:** a low-level building block. + `DigestUtils` and `HmacUtils` decorate the JCA (`MessageDigest`, `Mac`), + so the JDK-parity principle applies to them directly. +- **Family group:** parsers / format readers. +- **Typical untrusted-input surface:** + encoded text passed to decoders + (Base16, Base32, Base58, Base64, Hex, `BinaryCodec`, + `URLCodec`, `PercentCodec`, `QuotedPrintableCodec`, `QCodec`, `BCodec`); + passwords passed to `Crypt` and its implementations; + names passed to the phonetic encoders. +- **Side effects:** + methods that take a `Path`, `File` or `InputStream` read what the caller designates; + `GitIdentifiers.treeId(MessageDigest, Path)` reads the directory tree designated by the caller. + Symbolic links are not followed; their targets are included as link content. + `GitIdentifiers.TreeIdBuilder` constructs a virtual tree from caller-supplied values. + Codec reads its own classpath resources (Beider-Morse rules) + and the system properties listed below. + Encoded data is never interpreted as an instruction to access other resources or run code. +- **Command-line tool:** `org.apache.commons.codec.cli.Digest` digests the files named on its command line; + its arguments are trusted operator input. + +## Secure parsing + +**Codec does not claim the "secure parsing" guarantee.** +Applications that accept input from untrusted users +must bound it before passing it to Codec. +Reports that need malicious input are routed `OUT-OF-MODEL: no-secure-parsing-yet` +unless they break another property claimed by the family model or this profile. + +## Documented default resource limits + +The following inputs are bounded by default. +These limits are functional safeguards, not a claim that the entry points safely +process arbitrary malicious input. + +| Entry point | Default bound | Knob | +| --- | --- | --- | +| `Base58` encode / decode, including the streams | 8192 bytes | `Base58.Builder.setMaxEncodeLength` / `setMaxDecodeLength` | +| Beider-Morse (`PhoneticEngine`, `BeiderMorseEncoder`) | 666 characters | `PhoneticEngine.Builder.setMaxInputLength` | +| `Sha2Crypt` password length | 4096 bytes | system property `org.apache.commons.codec.digest.Sha2Crypt.keyMax` | +| `Sha2Crypt` `rounds=` taken from the salt | 1,000,000 | system property `org.apache.commons.codec.digest.Sha2Crypt.roundsMax` (at most 999,999,999) | + +Raising a bound is a trusted-operator decision. +Findings that require a raised bound or other trusted configuration remain out +of model under the family trusted-input rule. +Other encoders and decoders are expected to use resources appropriate to the +documented operation (family property 2); a violation there is a correctness bug. + +## Properties Codec does not provide + +### Canonical decoding + +Decoders are not injective: many encoded strings can decode to the same bytes. + +- The default `CodecPolicy.LENIENT` skips characters outside the alphabet, + ignores data after padding, + and accepts the standard and URL-safe Base64 alphabets together. +- `CodecPolicy.STRICT` rejects non-canonical Base32 and Base64 input: + trailing bits since 1.15, + alphabet, padding and line separators since 1.23.0. + `Hex` accepts only ASCII hexadecimal digits since 1.23.0. + +These are functional validation features, +not a security boundary, sanitizer or token-validation framework. +A representation they wrongly accept or reject is an ordinary bug +(family model: rejecting malformed input is not a security property). +Applications must not assume that two different encoded strings represent different values: +where a protocol defines a canonical textual representation, enforce it before +using the text as a security identity. Do not validate, cache, sign or deny-list +one representation while consuming a differently normalized representation. + +### RFC-exact parsing of the `net` codecs + +Differences between `QCodec`, `BCodec`, `URLCodec`, `PercentCodec` or +`QuotedPrintableCodec` and their documented RFC behavior or interoperable +implementations are functional correctness issues unless another claimed +security property is violated. Codec does not claim that these decoders are +security filters for downstream consumers. +Decoded output is as untrusted as its input (family output rule 1) +and may contain CR, LF, `/`, `..` or any other character. + +### Exception contract on malformed input + +Decoders document `DecoderException` or `IllegalArgumentException`. +An undeclared `RuntimeException` on malformed input is a robustness bug, not a vulnerability. + +### Digests, checksums and identifiers + +- `MurmurHash2`, `MurmurHash3`, `XXHash32`, `PureJavaCrc32`, `PureJavaCrc32C` and `Crc16` + are not collision resistant (family false friends). +- `DigestUtils` and `GitIdentifiers` use the JCA digest algorithm selected by + the caller; collision resistance is that algorithm's. + Offering MD2, MD5 or SHA-1 is not a finding (JDK parity). +- `HmacUtils` uses the caller-selected JCA MAC and caller-supplied key. Its + security depends on the selected MAC, the key and the protocol in which it is used. +- `GitIdentifiers` computes Git object identifiers and SWHIDs for interoperability. + Its output is a content address, + not a signature, MAC, attestation or proof of provenance. + Rejecting tree entry names that Git cannot represent (since 1.23.0) + is input validation; a gap in it is an ordinary bug (family output rule 3). + +### Password hashing + +`Crypt`, `UnixCrypt`, `Md5Crypt` (including APR1) and `Sha2Crypt` +implement the glibc `crypt(3)` formats for interoperability. + +- As a Codec-specific interoperability rule, merely reproducing behavior + defined by glibc `crypt(3)` is not a vulnerability. + Offering the weak legacy schemes (DES `crypt`, MD5-crypt) is not a finding. +- In the ordinary credential-store model, the salt string, including its + `rounds=` field, is trusted. + In the verification idiom `stored.equals(Crypt.crypt(entered, stored))`, + the stored hash is the trust anchor. + An application that hashes with salts from an untrusted source + must validate them. +- Codec does not provide constant-time comparison or password policy. + +### Blake3 + +`Blake3` is a pure-Java implementation of the BLAKE3 hash, keyed hash and KDF. +Output that differs from the BLAKE3 reference test vectors is a correctness bug. +No constant-time or side-channel claim is made (family model). + +### Phonetic encoders + +The `language` and `language.bm` encoders are fuzzy-matching aids. +Their output is not an identifier; collisions are their purpose. + +## Application responsibilities + +In addition to the family list, applications using Codec must: + +1. Bound untrusted input before passing it to Codec. Treat the default limits + above as defense in depth, not as authorization to pass arbitrary malicious input. +2. Define and enforce a canonical form wherever the textual representation + of encoded data affects a security decision. +3. Apply authentication (signature or MAC) at the protocol layer; + a digest or identifier alone is not one. +4. Choose a collision-resistant algorithm when an identifier backs an integrity decision. +5. Validate salts and `rounds=` values that do not come from the application's own password store. +6. Validate tree entry names passed to `GitIdentifiers` against the source format. + +## Known non-findings + +| Report | Disposition | +| --- | --- | +| "Base64, Base32 or Hex decoding accepts several spellings of the same bytes." | `BY-DESIGN: property-disclaimed` | +| "`CodecPolicy.STRICT` accepts input X." | Ordinary bug; `VALID-HARDENING` at most | +| "`QCodec` or `BCodec` decodes differently from mail client Y." | `BY-DESIGN: property-disclaimed` | +| "A decoder throws an undeclared runtime exception on malformed input." | `KNOWN-NON-FINDING` | +| "`DigestUtils` offers MD5 or SHA-1" / "`UnixCrypt` uses DES." | `OUT-OF-MODEL: jdk-parity` | +| "`Sha2Crypt` honors `rounds=` from the salt" / "costs quadratic time in password length", after a trusted operator raises the default bounds. | `OUT-OF-MODEL: trusted-input` | +| "Two trees collide because of the caller-selected digest algorithm." | `BY-DESIGN: property-disclaimed` | +| "Invalid or non-representable tree names produce an ambiguous `GitIdentifiers` serialization." | Ordinary input-validation bug; `VALID-HARDENING` at most | +| "Two distinct valid Git trees are serialized identically before hashing." | Functional correctness bug unless an identifier API is designated as a security boundary | + +## Conditions that would change this model + +- Codec claims the "secure parsing" guarantee for a stated version. +- Codec documents an API as safe for arbitrary untrusted input. +- Codec gains network access, format-driven ambient I/O, or code execution. +- A validation mode or identifier API is designated as an authentication, + authorization or attestation boundary. diff --git a/src/site/markdown/threat-model-short-1.23.0.md b/src/site/markdown/threat-model-short-1.23.0.md new file mode 100644 index 0000000000..5227be21c8 --- /dev/null +++ b/src/site/markdown/threat-model-short-1.23.0.md @@ -0,0 +1,108 @@ + +# Apache Commons Codec Threat Model (summary) version 1.23.0 + +This page is the short version of the +[Apache Commons Codec Threat Model](threat-model-1.23.0.html) +([Markdown](https://raw.githubusercontent.com/apache/commons-codec/master/src/site/markdown/threat-model-1.23.0.md)), +which is authoritative where the two differ. +Both apply the +[Apache Commons Threat Model 0.1.0](https://commons.apache.org/threat-model-0.1.0.html) +([Markdown](https://svn.apache.org/repos/asf/commons/cms-site/trunk/content/markdown/threat-model-0.1.0.md)) +to Codec 1.23.0 and later. + +Security researchers should use the +[full Codec threat model](threat-model-1.23.0.html) +([Markdown](https://raw.githubusercontent.com/apache/commons-codec/master/src/site/markdown/threat-model-1.23.0.md)). +Developers should use this page. + +## The model in brief + +Commons Codec is an in-process library of encoders, decoders, digests, +checksums, password-hash implementations, phonetic algorithms and related +utilities. It has no network listener, authentication or authorization layer. +The calling application is responsible for validating and bounding input at +its own trust boundary. + +**Codec does not claim the Commons "secure parsing" guarantee.** +Its documented default resource limits are functional safeguards and defense +in depth, not a promise that an API safely accepts arbitrary malicious input. + +Methods accepting a `Path`, `File` or `InputStream` read only the resources +designated by the caller. Encoded data is not interpreted as an instruction to +access other resources or execute code. + +## Decoding + +- Lenient decoders intentionally accept some non-canonical and malformed + representations for compatibility. +- `CodecPolicy.STRICT` provides stricter functional validation. It is not a + security boundary, sanitizer, authentication mechanism or token validator. +- Where encoded text affects a security decision, the application must define + and consistently enforce the protocol's canonical representation. It must + not validate, cache, sign or deny-list one representation while consuming a + differently normalized representation. +- Decoder differences from an RFC or another implementation are functional + correctness issues unless another claimed security property is violated. +- Decoded output is as untrusted as its input. Codec does not make decoded + paths, names, headers or other values safe for downstream use. + +## Digests, identifiers and passwords + +- Plain digests and checksums do not authenticate data. Use an appropriate MAC + or signature at the protocol layer. +- Security depends on the algorithm, key and protocol selected by the caller. + Codec continues to offer weak legacy algorithms for interoperability. +- `GitIdentifiers` produces content addresses, not signatures, attestations or + proofs of provenance. The caller must validate virtual tree names and choose + an appropriate digest algorithm. +- The `crypt(3)` implementations reproduce legacy formats for interoperability. + Codec does not provide password policy or constant-time comparison. + Applications importing salts or stored hashes from an untrusted source must + validate their parameters. +- Phonetic encoders are fuzzy-matching aids; collisions are intentional. + +## Developer responsibilities + +Applications using Codec must: + +1. Validate and bound untrusted input before passing it to Codec. +2. Treat Codec's default resource limits as defense in depth. +3. Enforce a canonical textual representation where a protocol requires one. +4. Apply authentication with a suitable signature or MAC rather than a plain + digest or content identifier. +5. Select suitable algorithms and securely manage keys. +6. Validate password-hash parameters received from outside the application's + trusted credential store. +7. Validate virtual-tree names against the source format and Git object model. +8. Treat all output derived from untrusted input as untrusted. + +## Reporting + +A report is a Codec vulnerability only if it violates a security property +claimed by the +[Commons family model](https://commons.apache.org/threat-model-0.1.0.html) +([Markdown](https://svn.apache.org/repos/asf/commons/cms-site/trunk/content/markdown/threat-model-0.1.0.md)) +or the [full Codec model](threat-model-1.23.0.html) +([Markdown](https://raw.githubusercontent.com/apache/commons-codec/master/src/site/markdown/threat-model-1.23.0.md)), +is reachable by an in-scope +adversary, and is not legitimate behavior for the underlying JDK facility. + +Report undisclosed vulnerabilities privately as described on the +[Apache Commons Security page](https://commons.apache.org/security.html). +Questions about published vulnerabilities belong on the public +[user mailing list](mail-lists.html). diff --git a/src/site/site.xml b/src/site/site.xml index aac51c1be1..41be9d8512 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -31,7 +31,12 @@ - + + + + + + diff --git a/src/site/xdoc/security.xml b/src/site/xdoc/security.xml index 47edf5d116..d48a186c61 100644 --- a/src/site/xdoc/security.xml +++ b/src/site/xdoc/security.xml @@ -30,6 +30,13 @@ For information about reporting or asking questions about security, please see Apache Commons Security.

+

+ The Commons Codec Threat Model + (Markdown) + applies to version 1.23.0 and later. + Developers can use its short summary + (Markdown). +

This page lists all security vulnerabilities fixed in released versions of this component.

Please note that binary patches are never provided. If you need to apply a source code patch, use the building instructions for the component version @@ -53,4 +60,4 @@

- \ No newline at end of file +