Vulnerability analysis · ARC verification

The dynamic string that arc_canon_runheaders() allocates in OpenARC outlives the message: arc_free() never reclaims it [OpenARC (master), latest release checked 2026-07-30]

Yongzhe Xu, Virginia Tech  ·  yongzhe@vt.edu  ·  2026-07-31

Header canonicalization runs for every ARC-verified message and leaks one string each time. No malformed input is needed; legitimate forwarded mail grows the verifier on its own.

SoftwareOpenARC (libopenarc)
VendorThe Trusted Domain Project
Sourcehttps://github.com/trusteddomainproject/OpenARC
AffectedCurrent upstream master. Newest published release checked on 2026-07-30.
Wherelibopenarc/arc-canon.c, arc_canon_runheaders(); the allocation from arc_dstring_new() is not released by arc_free()
WeaknessCWE-401 (Missing Release of Memory after Effective Lifetime)
Reachable byRemote. Leaks once per ARC-verified message; forwarded mail carries ARC chains by design.
CVSS v3.1CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L (5.3 (Medium))
VerificationLeakSanitizer-confirmed.

1. Overview

arc_canon_runheaders() in libopenarc/arc-canon.c allocates a dynamic string while canonicalizing the headers of a message. Nothing frees it. The message teardown path, arc_free(), does not reclaim it either.

Header canonicalization runs on every message the verifier checks, so the allocation is lost once per message. Memory grows in step with the volume of ARC-verified mail the process handles.

2. Analysis

LeakSanitizer reports a definite leak rooted at that allocation:

==ERROR== LeakSanitizer: detected memory leaks
  Direct leak of N byte(s) in M object(s) allocated from:
    ... arc_dstring_new <- arc_canon_runheaders ...

Nothing about the input has to be wrong. Any well-formed ARC instance that gets as far as header canonicalization leaks the string. Ordinary forwarded mail from conforming signers is enough to drive the growth.

3. Reproduction

  1. Build OpenARC with the sanitizer enabled.
export BUILD="$HOME/asan-build"
bash lib/build_openarc.sh
  1. Run the harness with leak detection on, first over a single seed and then over a

corpus of well-formed ARC messages, which shows the steady per-message growth.

ASAN_OPTIONS=detect_leaks=1 "$BUILD/fuzz_openarc" memory-safety/seeds/C7-arc-crash

# run over a corpus of well-formed ARC messages to show steady per-message growth
ASAN_OPTIONS=detect_leaks=1 "$BUILD/fuzz_openarc" corpus_arc/

4. Assessment

The exposed party is any long-lived OpenARC verifier handling forwarded mail. The attacker needs no authentication and no crafted input, since messages carrying ARC chains are exactly what the verifier is deployed to read. What they get is unbounded memory growth, ending in resource exhaustion.

The growth is slow and sustained volume is required, which makes this the least severe finding in the set. The absence of any input precondition is what keeps it worth reporting: legitimate traffic alone produces it.

5. Remediation

Free the arc_dstring in arc_free(). Releasing it at the end of canonicalization, once it is no longer needed, works equally well.

6. Additional notes

The null-pointer dereference openarc-c-tag-null-deref sits in the same ARC forwarding code path, which looks less exercised than the equivalent DKIM path.

Re-confirmation against the current OpenARC release is outstanding.

7. References