Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
196 changes: 196 additions & 0 deletions src/site/markdown/threat-model-1.23.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
<!---
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
# 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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does that even mean for an LLM? How many levels are there? Why not just point to the POM description?

`DigestUtils` and `HmacUtils` decorate the JCA (`MessageDigest`, `Mac`),
so the JDK-parity principle applies to them directly.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

applies to them directly

This hints that "the JDK-parity principle" would apply elsewhere "indirectly". What does that even mean?

- **Family group:** parsers / format readers.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the difference between a "parser" and a "format reader". A "parser" is a well-know term. I've never seen "format reader", it looks like made up term.

- **Typical untrusted-input surface:**
encoded text passed to decoders

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sentences start with a capital letter but there are not even complete sentences :(

(Base16, Base32, Base58, Base64, Hex, `BinaryCodec`,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ppkarwasz
Sometimes class names are styled, sometimes they're not. This should be consistent. Has anyone actually read this?

`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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is in the Javadoc, we should point to the Javadoc, otherwise ALL of this redundant text will slowly drift away.

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.
108 changes: 108 additions & 0 deletions src/site/markdown/threat-model-short-1.23.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<!---
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
# 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).
7 changes: 6 additions & 1 deletion src/site/site.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@
<item name="Issue Tracking" href="/issue-management.html" />
<item name="Dependency Management" href="/dependency-info.html" />
<item name="Sources" href="/scm.html" />
<item name="Security" href="/security.html" />
<item name="Security" href="/security.html">
<item name="Threat Model for Developers" href="/threat-model-short-1.23.0.html" />
<item name="Developer Model (Markdown)" href="https://raw.githubusercontent.com/apache/commons-codec/master/src/site/markdown/threat-model-short-1.23.0.md" />
<item name="Threat Model for Researchers" href="/threat-model-1.23.0.html" />
<item name="Researcher Model (Markdown)" href="https://raw.githubusercontent.com/apache/commons-codec/master/src/site/markdown/threat-model-1.23.0.md" />
</item>
<item name="License" href="https://www.apache.org/licenses/LICENSE-2.0" />
<item name="Code of Conduct" href="https://www.apache.org/foundation/policies/conduct.html" />
<item name="Download" href="/download_codec.cgi" />
Expand Down
9 changes: 8 additions & 1 deletion src/site/xdoc/security.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
For information about reporting or asking questions about security, please see
<a href="https://commons.apache.org/security.html">Apache Commons Security</a>.
</p>
<p>
The <a href="threat-model-1.23.0.html">Commons Codec Threat Model</a>
(<a href="https://raw.githubusercontent.com/apache/commons-codec/master/src/site/markdown/threat-model-1.23.0.md">Markdown</a>)
applies to version 1.23.0 and later.
Developers can use its <a href="threat-model-short-1.23.0.html">short summary</a>
(<a href="https://raw.githubusercontent.com/apache/commons-codec/master/src/site/markdown/threat-model-short-1.23.0.md">Markdown</a>).
</p>
<p>This page lists all security vulnerabilities fixed in released versions of this component.
</p>
<p>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
Expand All @@ -53,4 +60,4 @@
</p>
</section>
</body>
</document>
</document>
Loading