Skip to content

Bouncy Castle .NET parser, oracle, and constraint-bypass wave (Oct 2 09:31Z)

Source: hourly offensive-security scan of GitHub Security Advisories, 2026-10-02. ~20 GHSAs published 09:31Z for bc-csharp before 2.7.0 ("Legion of the Bouncy Castle Inc."), plus three Java BC pre-1.86 items in the same wave. Companion pages: July 1 BC CTR keystream, Aug 3 BC crypto-policy boundaries.

Why this matters to an operator: bc-csharp is embedded in .NET apps, Windows services, CMS document pipelines, PKI tooling, and IoT/OT management stacks. This wave is a complete catalogue of what an attacker gets when a product parses untrusted crypto objects with this library: padding oracles that recover plaintext keys, PKIX name-constraint bypasses for enterprise-pivot certificates, a forged-attribute-certificate auth bypass, and a resource-exhaustion inventory reachable pre-authentication.

Decision oracles: decrypt-and-report paths are key-recovery machines

Component GHSA / CVE Oracle
CMS RSA PKCS#1 v1.5 key transport (KeyTransRecipientInformation.UnwrapKey) GHSA-xx4m-xv2j-xx6g / CVE-2026-63573 Invalid padding rejected with a distinct "bad padding" exception instead of the RFC-required random-key substitution → textbook Bleichenbacher adaptive chosen-ciphertext: submit modified captured EnvelopedData, read the error taxonomy, recover the content key.
IES/ECIES block-cipher mode (IesEngine.DecryptBlock) GHSA-6w4x-4wpp-m6r4 / CVE-2026-63567 Decrypt + PKCS#7 padding strip happen before MAC verification; padding failure returns a different message and skips the MAC computation (also a timing differential) → CBC padding oracle on any app that surfaces decrypt errors.
IES stream mode (no block cipher) GHSA-43qj-h4fh-p2h4 / CVE-2026-16001 KDF output is laid out as keystream-then-MAC-key with the derivation input bound only to the static key pair, so the keystream revealed by one observed message with known plaintext contains the MAC key for every shorter message → forge arbitrary shorter ciphertexts accepted as authentic, permanently, for that key pair.
CCM AEAD (CcmBlockCipher, CMS EnvelopedData paths) GHSA-499v-wjw6-fvpx / CVE-2026-15999 Decrypt accepts an AlgorithmIdentifier whose aes-ICVlen is zero or outside the RFC 5084 set (tag length is validated only on encrypt); on-path attacker swaps parameters to a zero-length tag → content modification without detection.
DSTU 7624 CCM (KCcmBlockCipher) GHSA-m3jv-gj9x-qwrv / CVE-2026-16000 The G1 block binding nonce+length+flags into the CBC-MAC is processed only when associated data is present; no-AD messages get a nonce-independent tag → ciphertext forgery from known/chosen-plaintext observations.
CCM unverified-plaintext release GHSA-v84x-v65q-m82v / CVE-2026-103601 Failed decryption leaves recovered plaintext in the caller's output buffer (buffer reuse/logging oracle → chosen-ciphertext decryption service).
Raw DH agreement (DHAgreement.CalculateAgreement, MTI/A0) — critical GHSA-m2m9-m35w-rfxg / CVE-2026-63569 Peer ephemeral value raised to the static private key with no range/subgroup check: crafted small-order/out-of-range value makes both parties compute a key the on-path attacker already knows, and leaks the static private key modulo small factors of p−1.

Operator rules.

  1. Error taxonomy is the probe. For any endpoint that decrypts attacker-supplied crypto objects (CMS in document/email pipelines, ECIES in device provisioning, PFX upload forms), the finding is not "vulnerable library" — it is does a padding failure produce a different response than a MAC/tag failure? Differential battery: untampered / padding-corrupted / MAC-corrupted / truncated inputs; compare status, exception class, message text, and latency. A per-class differential = key-recovery oracle; report the exact differentiating field.
  2. Parameter-bearing AlgorithmIdentifiers are attacker-chosen and often only validated on the encrypt path. Sweep every AEAD/KDF/PBE algorithm parameter (aes-ICVlen, PBKDF2 iterations, scrypt N/r/p, OAEP label) through the decrypt/verify direction with degenerate values (0, 1, 2^31−1, out-of-set enums).
  3. Test static-DH APIs for small-order inputs. If a product calls raw DH agreement (not the authenticated TLS stack), submit a g^(p−1)-style order-1 element as the peer ephemeral and check whether the session proceeds.

PKIX validation bypasses (enterprise-pivot class)

Check GHSA / CVE Bypass shape
directoryName name constraints GHSA-437r-hr8h-5f45 / CVE-2026-63577 Subtree match searches for the constraint's first RDN anywhere in the subject and compares the rest from that position — prepend unrelated RDNs ahead of a copy of the permitted sequence → cert whose DN is outside the permitted subtree validates.
URI (uniformResourceIdentifier) constraints GHSA-3248-8mh4-pcmr / CVE-2026-63576 Host extracted by string slicing without isolating the RFC 3986 authority — a URI with @ or : in path/query/fragment userinfo makes the string compared against constraints differ from the real host.
DNS/email constraints, excluded subtrees GHSA-mx2f-845p-2h26 / CVE-2026-103602 Trailing-dot root label (evil.example.com.) fails to match an excluded subtree written without the dot → excluded names validate.
Attribute certificates (PkixAttrCertPathValidator) GHSA-cwfr-988g-hf77 / CVE-2026-63571 The RFC 3281 validation routine checks holder/issuer paths, validity, extensions, revocation — and never verifies the attribute certificate's own signature. A forged AC naming a trusted issuer grants whatever roles the app reads from its attributes.
PKCS#12 chain building GHSA-g2c8-ppvq-rq73 / CVE-2026-63570 Chain loop follows AuthorityKeyIdentifier links without visited-set and without checking signatures; two certs whose AKIs point at each other = infinite loop (CPU + OOM).

Operator rules.

  • Name constraints are the least-tested PKIX control. If an engagement yields any issuance capability from an enterprise intermediate (even a "locked-down" name-constrained one), test the three shapes above against a lab verifier before concluding the constraint actually confines you: prepend-RDN, authority-slicing URI (uri:user@real-host? shapes), trailing-dot FQDN. Constraint enforcement is verifier-side: also test client-side validators (TLS libraries, document signers, code-signing policy chains) separately from the CA's own issuance checks.
  • Attribute/role certificates: does the validator verify the signature at all? Any app granting privileges from X.509 ACs or holder-issuer bindings deserves a forged-AC test with an issuer name copied from a real AA. Zero cost, and the validation-stack skip is exactly what this advisory proves is plausible.
  • Path-building loops that trust unsigned identifier links are DoS + confusion primitives. Feed AKI-cycle pairs to any PFX/PKCS#12 loader.

Pre-authentication work-before-authentication: the resource-exhaustion inventory

The recurring shape across this wave: cost/length parameters are read from the untrusted object and consumed before any MAC, password, or signature can reject the input. That ordering — work first, authenticate later — is the audit predicate, not "is it a DoS."

Parser path GHSA / CVE Unbounded input → work
ASN.1 (Asn1InputStream/Asn1StreamParser) GHSA-xp76-rp77-x5w9 / CVE-2026-103600 No depth bound; ~2,000 nested SEQUENCEs (8 KB DER) exhaust the default .NET thread stack → uncatchable StackOverflowException kills the whole process. Any cert/CRL/CMS/PKCS#7 accepting path is a crash switch.
PKCS#12 load (Pkcs12Store.Load) GHSA-v54c-wxx6-mjh6 / CVE-2026-63572 + GHSA-7c84-x75c-5j8m / CVE-2026-63575 MacData/PBE iteration count taken from the file up to ~2^31 → KDF runs before the MAC or password is checked; zero/negative count wraps the loop through ~2^32 iterations. A 75-byte PFX ties up a worker for minutes.
Encrypted private keys (PbeUtilities, PBES1/PBES2/PKCS#12 PBE/CMS PBE) GHSA-4583-5v2w-p3vq / CVE-2026-63578 Same shape on ENCRYPTED PRIVATE KEY PEM upload forms.
CMP/CRMF PBMAC verifier GHSA-mm8p-p4g9-932c / CVE-2026-63568 Iteration cap enforced only when the caller used the explicit-maximum constructor — the convenient constructor runs attacker-chosen iterations up to 2^31 before the MAC check.
OpenPGP subpacket parsers GHSA-576x-9vpc-g3jj / CVE-2026-63574 Five-octet length form allocates up to ~2 GB from a few header bytes, never compared to the enclosing packet size.
HSS/LMS signatures GHSA-gpr4-c479-xrw4 / CVE-2026-103603 Level count from the public key unchecked against RFC 8554 max 8 → one verify allocates up to ~17 GB.
DTLS handshake reassembly GHSA-496x-2f25-59fj / CVE-2026-63566 Fragment buffer sized from the 24-bit declared length without the max-handshake-size check TLS already applies; an empty fragment allocates ~16 MB × 16 pending messages before the handshake is authenticated.
DN-to-string escaping (X509Name.ToString, RdnAreEqual) GHSA-p48w-99f8-9598 / CVE-2026-103604 Escaping inserts into the buffer being scanned → CPU grows quadratically with escaped-character count; fires when a cert name is logged/displayed or compared during PKIX directoryName constraint checks (same validator as the bypass items above).

Operator rules.

  • Fuzz battery for every untrusted ASN.1/PKCS/OpenPGP consumer (cert/CRL upload, PFX import, S/MIME handler, OpenPGP key server, DTLS listener, CMP enrollment endpoint): depth-nested SEQUENCEs (8 KB → process death on .NET defaults), max-length five-octet subpacket headers, iteration-count 2^31−1 and −1, HSS/LMS level-count 2^32, DTLS fragments declaring 16 MB with zero payload. These are the shapes with published, specific thresholds now — they are one-liner generators, and pre-auth ones.
  • "Cap-before-derive" is also an audit rule for integrators: when a product embeds this library, its own wrappers frequently reintroduce the unbounded constructor path (the PBMAC constructor split is the exemplar — the safe API exists, the default one is unsafe).

Java BC (before 1.86) adjacent legs

  • NTRU secret-dependent division (GHSA-frjj-v5w4-68pc / CVE-2026-18036): modQ/mod3 helpers used integer % on secret operands where the reference implementations are deliberately division-free — variable-latency division on the decapsulation path (dividend derives from the private key). Post-quantum KEM side channel in the reduced-secret handling, not the core math — audit pattern: check every modular reduction in a PQC port against the reference's division-free construction.
  • MLS signed/unsigned leaf index (GHSA-x7w3-c4mv-whm4 / CVE-2026-17507): RFC 9420's uint32 leaf_index held in a signed int; a wire value with the top bit set is a legal encoding (interop vectors round-trip the full range), and signed comparison against leaf count makes any negative index pass the membership check → any group member DoSes the whole group via unbounded directPath arithmetic. Axis: signed/unsigned parse differential — same family as the negative-length/offset items on the parser pages; a spec says "full uint32 range decodes", so the fix must reinterpret, not reject-on-negative. (MLS roster-trust companion to the Oct 2 Discord libdave item on the messaging-SDK page.)
  • KDF cost parameters from untrusted input (GHSA-m3x3-p27c-whhp / CVE-2026-17508): PBMAC1 iteration count, scrypt p (bounded N/r but scratch scales with r×p, evading the memory ceiling), raw JCA PBKDF2, bcrypt rounds read from an OpenSSH v1 key's own kdfoptions — the Java twin of the .NET work-before-authentication class; OpenSSH rounds now capped via org.bouncycastle.openssh.max_rounds.

Validation workflow (lab scope only)

No production crypto endpoints

All oracle and exhaustion proofs run against lab builds/disposable services you own with synthetic keys and certs. Bleichenbacher/padding-oracle proofs need only enough iterations to show the differential exists (a handful of classification queries), not full key recovery. Never run memory-exhaustion shapes against shared or production hosts — allocate in a constrained VM and measure.

  1. Oracle decision table: for each decrypt endpoint, submit untampered / padding-corrupt / tag-corrupt / truncated variants; table status+message+latency per class. Any separation = oracle; stop there.
  2. Parameter-degeneracy sweep: replay CMS/PKCS structures with aes-ICVlen=0, iterations 0/−1/2^31−1, scrypt p unbounded — assert the decrypt direction validates parameters, not just encrypt.
  3. Lab PKIX constraint harness (Java/Go, no network): build a name-constrained test CA with openssl, issue prepend-RDN, trailing-dot, and authority-sliced URIs certs; run the target verifier and diff accept/reject vs RFC 5280 expected.
  4. ASN.1 depth generator: 8 KB nested-SEQUENCE DER sent to cert/CRL/CMS ingestion in a lab process with default thread stack; observe StackOverflow vs caught exception (this also tells you whether the app's host swallows crashes).
  5. PFX micro-DoS timer: 75-byte PFX with negative MacData iterations against a lab PFX import form; measure worker occupancy with a stopwatch, not a profiler.

October 2 late-wave follow-up: wolfSSL cert-validation pack — the same constraint/verdict axes in an embedded TLS stack

A wolfSSL ≤5.9.x pack landed in the 21:33Z updated-feed wave. Distinct library, same three invariants this page was built on (constraint enforcement is verifier-side; the verdict object can lie; work-before-auth ordering):

  • Name-constraint state machine resets on an unconstrained intermediate (CVE-2026-89133 / GHSA-vrp7-vcfx-j447, default build): an unconstrained CA tier between a name-constrained intermediate and the leaf resets validation state → certs for out-of-scope hostnames accepted. Second verifier-side name-constraint bypass family this week (BC .NET trio above); the prepend/tail-dot/URI-slicing battery should now include this chain-shape leg: constrained intermediate → unconstrained tier → leaf.
  • CN-fallback gate tests the wrong predicate — an incomplete fix of CVE-2026-6731 (CVE-2026-89134 / GHSA-p2xv-vrwq-543q, 9.1): the Subject-CN-as-dNSName fallback is gated on altNames == NULL instead of "no dNSName SAN", so a cert carrying only registeredID/iPAddress SANs skips name constraints on its CN. Audit rule: fix-gating predicates deserve their own differential — present each SAN-type combination (none / dNSName / non-dNSName / mixed) and diff which leg consults the constraint.
  • MatchTrustedPeer ignores the public key (CVE-2026-93302 / GHSA-22fm-4q7r-f7w4, 8.2): with WOLFSSL_TRUST_PEER_CERT (default in autoconf builds: nginx, haproxy, stunnel, apache, bind, rsyslog…), a forged CA clone with the same subject but a different key passes peer verification → (D)TLS server-auth bypass once the attacker knows which peer certs are loaded. Peer identity pinned by name not key is the X.509 twin of the non-secret-identifier-as-credential class (Fleet, Oct 1).
  • A failed verify poisons the shared CertManager for every sibling consumer (CVE-2026-89135 / GHSA-m732-8qwx-39wm): an X509_verify_cert failure permanently plants the unverified attacker CA in the shared store consulted by native TLS, OCSP, CRL, and direct verifies. One rejected-then-cached object = persistent validation bypass across unrelated features. Sweep rule: for any verify-then-cache path, attempt verify-with-bad-material → re-verify-good-request and check whether trust changed state; caches keyed on parsed names that store failed verdicts are state-corruption primitives.
  • Split verify inverts error precedence under WOLFSSL_SMALL_CERT_VERIFY (CVE-2026-94418 / GHSA-q4rg-xp99-jj6q, low CVSS / high practical): signature check runs separately from parse and the result merges only when parse returned 0, so parse errors mask signature failure and validity-date/name-constraint checks are reached without a passed signature — a self-made cert with the trusted CA's subject as issuer and garbage signature bytes is accepted. "Override date errors" policies become total bypasses when the split ordering inverts.
  • Out-of-order ChangeCipherSpec installs known-key read keys (CVE-2026-93304 / GHSA-vpg5-xh2g-4x3c): a TLS/DTLS 1.2 client accepts CCS before ClientKeyExchange, derives read keys from the deterministic null master secret, and checks the server Finished against it → an on-path attacker completes the handshake in place of the server and injects data the client accepts as authentic. CCS-injection regression family (the 2014 RFC 7507 class) alive in a current embedded stack; DTLS clients exposed by datagram ordering alone. Tester note: handshake-state probes (early CCS, early Finished, record reordering) belong in any embedded-firmware TLS battery, lab MITM position only.

Collective fingerprint: wolfSSL underpins appliances, printers/cameras, OT gateways, and load/edge daemons shipped via distro autoconf builds — for any binary that strings to wolfSSL, the six legs above are one battery: chain-shape constraint reset, SAN-type matrix, trusted-peer clone, poisoned-verify replay, split-verify garbage signature, early-CCS injection. All proofs: lab MITM/disposable endpoints, synthetic CAs.

Tracked without publication (same Oct 2 09:31Z wave)

  • cPanel/WHM trio: Mass Modify Accounts stored XSS→code execution (GHSA-jc78-m6vr-f88f), Manage SSL Hosts stored XSS (GHSA-cc4m-c4vh-cj6w), Multilang adminbin cmdi (GHSA-hw2c-444c-65c4) — all critical but zero technical detail; admin-panel-position XSS class already canonical, revisit if sink detail lands.
  • JSON API Auth cached-cookie ATO folded separately onto the Sept 19 WP alternate-surface page.
  • MStore API <4.22.1 client-controlled order fields → unpaid→paid (GHSA-2gpc-rx3g-g49h); WebToffee Gift Cards <1.3.1 unvalidated/negative gift-card amount as cart price (GHSA-5v9w-gc32-w7g2) — client-trusted-amount/price axis canonical on the Sept 23 WC payment page.
  • Dc Woocommerce Multi Vendor ≤5.0.18 order_by ORDER BY SQLi where esc_sql() protects only quoted literals (GHSA-xgpw-mm25-3whc) — sort-column-into-SQL class already canonical (Fleet/ClickHouse, TDuckCloud, iFlytek).
  • HAVELSAN Sef AI Chatbot SSRF/cert-validation/missing-authz trio (GHSA-pg74-28w9-6j58, GHSA-679g-qgm4-wf24, GHSA-352f-59q8-5jw5) — detail-free single-vendor pack.
  • gotop local argument injection on process-kill (GHSA-pm6f-qrm6-v363) — local-position class.
  • FreeType CID font loader flaw, Repasat XSS trio, Event Tickets generic SQLi, and ~25 generic WP stored/reflected XSS + option-write singles (Relevanssi pair, CMB2 pair, Download Manager/Monitor, Greenshift, Smash Balloon, JetFormBuilder, Kubio, MW WP Form, Newsletter, GSpeech, Otter, DoFollow, No External Links, Customer Reviews, Listdom, Mang Board, BA Book Everything, WP Edit Password, Easy PayPal button, WP User Frontend, WP Mail Logging, Popup Maker, Motors, Events Calendar, CTX Feed admin eval) — sanitizer/IDOR/missing-cap singles with no new axis; several are siblings of items already canonical on the Sept 19 WP pages.

October 3 09:31Z follow-up: Java BC before 1.86 — credential-binding omission, index-zero name constraints, OpenPGP authority gaps, and an always-false comparison

The 09:31Z Oct 3 wave published ~10 GHSAs for Bouncy Castle for Java before 1.86 (plus LTS 2.73.13 for the JNI item) — the Java twin of this page's .NET wave, and it lands on the same invariants (binding is verifier-side; verdict objects can lie; parse-equality is not authority).

  • MLS credential never bound to the leaf's signature key — admission under a victim's identity (critical) (CVE-2026-71885 / GHSA-jch3-5j66-88vx): LeafNode.verify() checked the leaf signature against the signature_key carried in the leaf itself while the X.509 credential chain was stored but never parsed or validated — RFC 9420 §5.3 requires the end-entity cert's public key to match signature_key. An attacker presents another party's certificate as its credential, signs with an unrelated key, and is accepted under that identity through KeyPackage.verify() and the Group leaf-validation path; where a deployment admits external commits without an independent credential-admission check, an unauthenticated attacker joins the group under a victim's identity. Sibling leg: external-commit Remove proposal had no joiner binding (CVE-2026-71890 / GHSA-jc55-7frr-fv5r) — validateExternalCachedProposals counted proposal types and bounded the removed leaf index but never checked the removed leaf had anything to do with the joiner (RFC 9420 §12.2 self-remove rule deliberately skipped on this path with nothing put in its place). Durable rule: a credential that is parsed-but-not-verified is absent — for any protocol carrying cert+key pairs, diff what the verifier actually compares (key-to-identity, key-to-signature) against what the spec requires; then test admission with a swapped-in foreign credential on lab group members. This is the same subject-not-key class as the wolfSSL MatchTrustedPeer leg above, one layer up the stack.
  • PKIXCertPathReviewer skips name constraints on the leaf — loop bound excludes index zero; and it disagrees with CertPathValidator("PKIX","BC") on identical input (CVE-2026-71889 / GHSA-hqqj-v58h-gr7x): checkNameConstraints walked with index > 0 (the CA-only bound), but index zero is the target cert in standard CertPath ordering — RFC 5280 §6.1.3(b)/(c) never ran against the leaf's DN or SAN; a chain violating its own issuing CA's NameConstraints reports isValidCertPath() true with an empty error list. Third verifier-side name-constraint bypass family this week (after the .NET trio and the wolfSSL chain-shape leg), and the two-verifier differential is the probe: same library ships two PKIX paths with no shared code that disagree — a product using the reviewer instead of the PKIX validator silently drops leaf constraint enforcement. Audit rule: for any app embedding BC, check which verifier class the product calls; decision-table the same chain through both when source is visible.
  • OpenPGP: key flags are decoration unless the verify path consults them — two legs. (1) Third-party certification accepted from any component key of the issuing certificate without the CERTIFY_OTHER flag — a SIGN_DATA-only online signing subkey issued a positive User ID certification over attacker-controlled identities (CVE-2026-71886 / GHSA-7hrr-mw36-px4x): getCertificationBy()/getDelegationBy() match the issuer key ID against every key and verify the binding chain + signature, nothing checks authority-at-signing-time. (2) A signing subkey whose binding signature omits the Key Flags subpacket fell back to inheriting the primary's SIGN_DATA via a different resolution path than the one that enforces cross-certification, so the missing Primary Key Binding signature check was skipped (CVE-2026-71887 / GHSA-cwf6-pghv-hq93). Durable axes: capability flags that the verify path doesn't re-read are advisory — test whether a low-authority key (sign-only subkey, no-flag binding) can perform high-authority operations (certify, delegate); and same-structure-two-resolutions (flag lookup falling back to parent when absent) is the subpacket twin of the fail-open parse pattern on the Sept 20 media page. Battery: build keys with every flag/subpacket omission combination and run the certification + binding verification matrix.
  • Truncated OpenPGP message = clean end-of-message; SEIPD v1 released cleartext with no integrity check at all (CVE-2026-85515 / GHSA-8hgf-w73g-3x6v): truncation was detected, then nextPacketTag() translated the EOFException into end-of-stream, so the packet stream "finished normally"; consumers releasing streaming cleartext get attacker-truncatable messages. Axis: EOF-as-success in streaming parsers — append-truncation probes to any decrypt/verify stream and diff "error reported" vs "clean short message"; RFC 9580 §13.7 permits partial release only with a clear truncation error.
  • CMS AuthenticatedData: MAC coverage chosen on the wrong field (CVE-2026-71888 / GHSA-j453-27jp-4cph): the streaming parser must choose MAC-coverage (authAttrs vs eContent) in its constructor before reaching authAttrs, so it chose on digestAlgorithm presence alone — absent digestAlgorithm + present authAttrs verifies the content MAC then returns the unauthenticated attributes as if authenticated. In-transit modifier can swap authenticated attribute content. Axis: streaming parsers that must decide before they've parsed create field-pair consistency gaps — send every presence/absence combination of paired fields (digestAlgorithm/authAttrs is the exemplar) and check which copy of the data the verdict is computed over.
  • Type-mismatched comparison makes a security check dead code: byte-array vs OID equals() is false for every input (CVE-2026-71892 / GHSA-x42w-4gqh-qrvm): the opt-in CMS key-size validation branch for RFC 9709 HKDF key derivation compared the encrypted-key byte array against the id-alg-cek-hkdf-sha256 OID object — always false — so the check silently fell through to a key-size lookup on the outer wrapper OID. Audit grep: any equals(…)/== where operand types are not statically comparable is a permanent-false branch; for opt-in security flags, prove the enabled flag actually changes a verdict with a minimal harness before trusting it.
  • JNI release-mode 0 commits the native copy back into the caller's key/IV/AAD arrays (CVE-2026-71883 / GHSA-f5wg-4mfp-h458, LTS <2.73.13): one-shot native packet ciphers released read-only inputs with ReleaseByteArrayElements mode 0 — on copy-not-pin JVMs the copy still holds the input bytes and gets committed back, and because the output buffer commits first, in-place calls (encrypt(keyArray, …, keyArray), e.g. over KeyParameter.getKey()) get key material overwritten with derived data. Axis for integrators: JNI native wrappers mutating "read-only" Java arrays — in-place crypto call patterns are the detector; key material destroyed mid-session is both a confidentiality and correctness bug, and the differential (pinning vs copying JVM flags) is the reproduction lever.
  • BLS12-381 keyValidate trusts the point's own curve to name its cofactor (CVE-2026-71891 / GHSA-gggh-4cvh-v637): ECPoint.satisfiesOrder() returns true outright when the curve's cofactor is one, so a point on a foreign curve with the same field characteristic and a cofactor forged to 1 passed validation despite not being a G1 point; in BC's pairing implementation such a point maps to the identity in the target group — poison public keys pass every BasicScheme/MessageAugmentation/ProofOfPossession verify and aggregate. Invalid-curve class, durable leg: subgroup checks that delegate curve parameters to the untrusted object being checked. Probe: craft a same-prime, different-equation curve, check whether the validator's point-on-curve + order checks reject it.
  • HQC side channels: table-indexed GF(2⁸) arithmetic + early-exit duplicate scan in the fixed-weight sampler (CVE-2026-18040 / GHSA-rxw8-22c7-wgq6, medium): both run on secrets during encaps/decaps, and the sampler re-expands the seed on every decapsulation — cache/timing surface on the PQC private key. Adds a third PQC side-channel family beside the NTRU division leg above; audit battery for PQC ports: table lookups on secret indices, secret-dependent branch exits, and per-decap secret re-derivation (amplifies every observation).
  • PBES1/PKCS#12 PBE: unbounded iteration count from untrusted AlgorithmParameters before anything is verified (CVE-2026-97873 / GHSA-78x9-mjv2-rr3v, medium): intValue() even narrowed >int values; the Java twin of the .NET work-before-authentication inventory already on this page — same degenerate-count sweep (0 / −1 / 2³¹−1) applies to PKCS12PBE/PBKDF1 Cipher/Mac/SecretKeyFactory paths.

Collective fingerprint update: the Oct 2 page's rules ("error taxonomy is the probe", "parameter-degeneracy sweep", verifier-side constraint enforcement) now cover both BC implementations; any Java/Android/IoT-TLS/PKI product on bcprov should be fingerprinted for the reviewer-vs-PKIX-validator choice, the MLS credential path, and OpenPGP high-level API use. Proofs stay lab-only: disposable groups/keys, synthetic certs, harness-level differentials, never production crypto endpoints.

October 2 22:3xZ follow-up: Xray-core pinned-CA MITM via empty ServerName (folded, same wrong-predicate class as the wolfSSL pack)

  • pinnedPeerCertSha256 on a CA = MITM enabler when ServerName is empty (GHSA-5wf9-h793-w73c, high): pinning sets Go tls.Config.InsecureSkipVerify = true and verifies against the pinned chain instead — but Go's Verify(opts) only checks dNSName/iPAddress when ServerName is set. The hysteria dialer and the gRPC dialer with an IP address build GetTLSConfig() without WithDestination(dest), leaving ServerName empty: an attacker who gets any leaf issued under the pinned well-known CA (their own domain) passes the pin and hijacks the connection. Durable axes: (1) custom pinning replaces, not supplements, Go's verification — audit every construction site of the TLS config for the destination-binding call; alternate transports (hysteria/gRPC/transport variants) are the sites that miss it (alternate-path drift again); (2) pin-equality-or-hash checks that skip name constraints convert a CA pin into "any leaf under this CA" — the same subject-not-key class as the wolfSSL MatchTrustedPeer leg above. Operator angle: for proxy/VPN fleets pinning well-known CAs, an on-path position plus a cheap LEAF under that CA breaks the pin — probe pin configs, then leaf-chain acceptance.

October 4 18:3xZ follow-up: default-insecure TLS helpers in shared SDK/client code (gopay, go-micro, Cockpit CMS)

Three same-wave advisories are the default-flag twin of this page's wrong-predicate pack — verification isn't mis-implemented, it's switched off in a helper every integrator inherits.

  • gopay payment SDK before 1.5.119 — defaultClient() sets InsecureSkipVerify in pkg/xhttp/client.go (CVE-2026-105218 / GHSA-8f6w-7m2h-mfwg, critical): merchant credentials, signatures, and transaction data cross a TLS leg that accepts any certificate; payment/refund/order-query responses are also modifiable in transit. On-path MITM impersonates the payment provider API to the merchant app — the response-modification leg means an attacker can flip a payment-status answer, not just read it.
  • go-micro before 6.0.0 — shared TLS helper sets InsecureSkipVerify: true by default (CVE-2026-105216 / GHSA-p6q5-cmw8-pqqg, critical): one helper, three planes — gRPC transport, HTTP, RabbitMQ broker, and Consul/etcd registry traffic all inherit the flag, so auth tokens and service credentials are interceptable mesh-wide from any network position inside the fabric. A single default silently de-authenticates the entire service-mesh trust model.
  • Cockpit CMS 2.12.0–<2.14.1 — cron.php web-worker restart request skips cert verification (CVE-2026-105217 / GHSA-7gf3-cfh5-c772, low CVSS but durable shape): the outbound call to site_url carries the worker/web token, so an on-path attacker on that leg steals the token and can start the web worker themselves. Shape to reuse: an admin/config-stored URL as the destination of an unverified outbound request that embeds a privileged token = token-theft pivot from a network position, even when the token's own endpoint is well-authenticated.

Durable rules: (1) library-default bypasses are invisible to app-level config review — defaultClient()/shared TLS helper names are the grep targets (InsecureSkipVerify, verify=False, VERIFY_NONE, rejectUnauthorized: false) in dependency source, not just app config; any Go/Python/Node SDK shipping a default client deserves this grep before you trust its transport. (2) One shared helper = blast-radius multiplier: count how many transports/planes inherit the flag (go-micro: RPC + broker + registry) — a default-on-insecure helper in mesh middleware is a fabric-level MITM primitive, and pentest evidence only needs one intercepted inter-service call to prove it. (3) The token-in-unverified-outbound-request shape pairs with the Xray empty-ServerName leg above: both steal or bypass at the client construction site, which is where audits stop looking. Validation stays passive/lab: on-path position on your own lab mesh or a synthetic merchant callback harness; never intercept live payment or production mesh traffic.

October 5 00:3xZ follow-up: verification off in shipped config stubs and gem defaults (google-maps Laravel, gist RubyGem)

Two more critical same-class legs extend the grep target list beyond code helpers into the files nobody audits:

  • alexpechkarev/google-maps Laravel through 12.16 — bundled config sets ssl_verify_peer => FALSE, passed to CURLOPT_SSL_VERIFYPEER (CVE-2026-105222 / GHSA-mpgp-p4pg-fp7c, critical 7.4): Google Maps web-service requests cross an unverified leg; on-path presents any cert, steals the API key from the query string, and tampers with geocoding/directions responses. Two amplifiers worth noting: the default ships in the package's publishable config stub (Laravel vendor:publish copies it into the app tree where it becomes invisible app config — the grep target is the vendor config file, not just curl calls), and key-in-query-string means one interception yields a persistent credential, not a one-session read. API keys in query strings + unverified transport = steal-once MITM; flag both legs.
  • gist RubyGem before 6.1.0 — http_connection in lib/gist.rb sets VERIFY_NONE (CVE-2026-105221 / GHSA-phqh-xp3p-h6mr, critical 7.4): GitHub API traffic (OAuth token, credentials) interceptable by any on-path cert. CI/gist tooling is a common runner dependency — a gem's own HTTP builder defaults are as exploitable as app config, and CLI tools embedding the gem inherit it silently.

Updated fingerprint: the dependency-source grep now covers four artifact shapes — shared client helper (gopay/go-micro), config-stored destination + unverified outbound (Cockpit), shipped config stubs with insecure flags (ssl_verify_peer, CURLOPT_SSL_VERIFYPEER, verify => false inside config/*.php-style vendor stubs), and gem/package-internal HTTP builders (VERIFY_NONE, OpenSSL::SSL::VERIFY_NONE). On any PHP/Ruby engagement, grep installed vendor trees for these tokens before trusting any outbound leg; proof = own on-path harness with self-signed leaf + synthetic key marker, never live traffic.

October 5 03:3xZ follow-up: kubernetes-client npm — missing CA material fails open, and the explicit opt-out is ignored (fifth artifact shape)

  • maclof kubernetes-client 0.17.0–<0.32.0 (CVE-2026-105223 / GHSA-52r7-jqcr-m8h9, critical 7.4): parseKubeconfig()/parseKubeconfigFile() disable TLS certificate verification whenever the kubeconfig lacks certificate-authority-data — instead of erroring or requiring an explicit opt-in — and simultaneously ignore insecure-skip-tls-verify: false. On-path the API server is impersonable with any certificate: Bearer tokens and Basic credentials captured, REST and WebSocket (exec/logs/attach) traffic tampered.

Two new axes for this family: (1) absence-of-trust-material fail-open — every prior leg was an explicit default flag; this one is implicit downgrade when parsing finds no CA data. Audit any config/file loader for the branch taken when the trust field is missing: error, refuse, or silently proceed unverified? Grep kubeconfig/loader code for certificate-authority handling branches and test with a minimal kubeconfig omitting the field against your own fake API server. (2) Security-relevant fields read but never enforced — the parser parses insecure-skip-tls-verify and then doesn't act on it, so an operator who explicitly opted in to verification still gets none; enumerate parsed-but-unused security fields in config loaders (parse site vs consume site parity, the same grep this page's Airflow deserializer leg uses). Target-richness note: npm kubeconfig consumers (CI tooling, dashboards, operator scripts) are common in DevSecOps chains; a fake API server with a self-signed leaf proving token capture from an omitted-CA kubeconfig in your own lab completes the proof — never against a live cluster.

October 6 follow-up: sequoia-openpgp — missing key-flags subpacket defaults to permissive capability inference (CVE-2026-42784 / GHSA-g33h-rrj9-75qv, high)

sequoia-openpgp inferred key capabilities for older certificates when the key flags subpacket is absent, producing a capability view that differs from stricter implementations — the confusion bypasses the back-authorization (back-signature) check, so an attacker can bind an arbitrary subkey to someone else's certificate and forge signatures attributed to the primary key holder.

  • This wave's invariant restated for OpenPGP: a missing security-relevant subpacket must resolve to the most restrictive capability, and implementations must agree on the resolution. The BC legs above were explicit-check misses (unbound credential, index-zero skip, unchecked flag); sequoia is the default-inference variant — same verifier-disagreement outcome as the PKIX two-verifier leg (hqqj), reached by omitting a subpacket instead of misparsing one.
  • Operator probe for any OpenPGP-family verifier under test (authorized lab only): craft a keypair where the subkey binding signature is forged in the no-key-flags state, present it to (a) the target library, (b) reference GnuPG, and diff accept/reject — a library that accepts where GnuPG rejects is the finding. Same two-verifier decision-table method this page used for the CMS authAttrs MAC-coverage leg.
  • Generalization for format audits: for every optional security field in a wire/hybrid format (PGP subpackets, SAML conditions, X.509 extensions, JWT claims), enumerate the absent-field branch of each consumer — absent-→-allowed is this week's recurring miss (sequoia here, Keycloak claim-verification legs, the SPIP omitted-secu_-param dispatch on the Oct 5 Joomla page's family).

October 6 15:3xZ follow-up: MsQuic OpenSSL/QuicTLS backends skip TLS hostname verification (GHSA-w5f4-fx9m-m4q7 / CVE-2026-105794)

Microsoft's MsQuic library with the OpenSSL or QuicTLS TLS backend performed no certificate hostname check on the QUIC connection — an on-path attacker presents any CA-valid cert (for any name) and completes a QUIC/TLS session impersonating the target. Schannel is not affected. Fixed in 2.6.1 / 2.5.11 / 2.4.20.

  • Page invariant extended to QUIC: hostname verification is per-stack, not per-protocol-suite. The same product passes a TLS test through Schannel and fails through OpenSSL depending on the shipped backend — fingerprint the backend (package name Microsoft.Native.Quic.MsQuic.OpenSSL carries it in the advisory) before trusting any "TLS works" observation. Test matrix for authorized QUIC targets: self-signed-but-accepted-lab-CA cert with wrong SAN vs correct SAN; if both connect, you have the finding.
  • Standing fingerprint value: HTTP/3 and QUIC-only services (h3 alt-svc) built on MsQuic managed wrappers before these versions were silently name-check-blind; the QUIC handshake completes with a mismatched leaf. Pair with this page's Xray-core empty-ServerName and wolfSSL legs — three independent stacks in one week where the verification step itself was the missing component, backend-conditional each time.

October 6 23:3xZ follow-up: PyJWT accepts OKP JWKs whose declared public key doesn't match the private key (GHSA-x33g-cr3x-6449 / CVE-2026-102275)

PyJWT 2.1.0–2.14.0 OKPAlgorithm.from_jwk() checks that x is present but, when d is also present, builds the Ed25519/Ed448 key from d without verifying the public key derived from d matches the declared x. A JWK can therefore carry one public identity while all crypto operates on a different key — in DPoP integrations this lets a stolen sender-constrained access token be used without the legitimate holder's private key (construct a JWK declaring the victim's x but supplying any private d; the proof binds to d, the identity reads as x). Fixed 2.15.0.

  • This is the inconsistent-field branch sibling of this page's absent-field branch rule: audits already sweep what happens when a security-relevant field is missing; this leg asks what happens when two coupled fields are present but disagree. For every paired/derived field in a token or key format (x/d, kid/key-material, alg/key-type, JWE alg/enc), enumerate the mismatch case — validators that check presence-of-each and use-of-one never test the cross-check.
  • Operator probe for DPoP/sender-constrained stacks under authorized test: submit a JWK with mismatched x/d through the token path and observe whether validation resolves identity from x while signing with d; the differential is a valid-looking DPoP proof from a key nobody authorized. Prove with synthetic keypairs only, never real captured tokens.

October 7 follow-up: Apache Commons BCEL caches classes under their self-declared name — verifier-result poisoning across the whole ClassLoader (CVE-2026-94114 / GHSA-2p8h-ph4h-rm2f, high, fixed 6.13.0)

The fix diff (commit 14890bf2) says it plainly: AbstractClassPathRepository.loadClass / ClassLoaderRepository.loadClass parsed a class file and cached it under the this_class name declared inside the attacker-controlled bytes instead of the requested lookup name — so delivering a class file whose internal name claims com.victim.Trusted while being found under an attacker-writable location poisons the repository entry for the real class, and every subsequent lookup and name-keyed verification result resolves the impostor. The fix adds the check the JDK's own defineClass has always enforced (requested == declared or reject); the static global Repository/VerifierFactory made the poisoning ClassLoader-wide.

  • Third branch in this page's field-identity family: absent-field (permissive capability inference), inconsistent-paired-field (x/d), and now self-declared-name-as-cache-key: whenever a cache/map key originates from the payload's own content instead of the lookup request, one attacker-authored object rebinds a victim's identity. Sweep rule for any parser/repository/registry that keys by an in-band declared name (Java class repositories, XML/X509 subject names, package metadata name fields, checkpoint/manifest id fields): feed one artifact whose declared key names a different legitimate object and check which one future lookups return.
  • Target-facing relevance: BCEL sits under static analyzers, bytecode verifiers, and plugin/serialization validators — when the verifier's view of a class is poisonable, signed-jar/allowlist checks keyed by class name inherit the poison. Proof shape: two disposable synthetic classes (Marker declaring FakeTrusted), load through the repository, show the second lookup by FakeTrusted returns the Marker bytes; lab-only, no production analyzer runs.

October 7 03:30Z follow-up: wolfSSH coordinated wave — the SSH transport's own verification steps are missing (4 promotable legs of 5)

wolfSSH through 1.5.0 shipped a coordinated advisory set at 03:30Z that extends this page's "the verification step itself was the missing component" family from TLS backends into the SSH protocol layer:

  • ECDSA host-key curve substitution MITM (GHSA-c487-h25j-24jq / CVE-2026-16516, critical): ParseECCPubKey() derives the curve from the algorithm string inside the KEXDH_REPLY host key blob (NameToId/wcPrimeForId) and discards the RFC 5656 curve identifier via GetSkip() instead of comparing it to the negotiated ssh->handshake->pubKeyId. An on-path attacker substitutes a host key blob on any ECDSA curve it controls the private key for, and signature verification passes because the key is imported on the wrong curve — host authentication is silently voided. This is the negotiated-vs-in-band-declared-identifier mismatch branch of this page's field-identity family (absent-field, paired-field mismatch, self-declared-name-as-cache-key, and now declared-identifier-vs-negotiated-result): the handshake did agree on a curve; the parser never checks the payload against that agreement. Probe for any SSH/embedded-TLS stack under authorized test: force a KEXINIT offering ecdsa-sha2-nistp256, then deliver a reply blob declaring a different curve identifier, and record whether the client completes the handshake — completion with attacker-key material is the finding (own on-path harness, never live targets).
  • KEX message-direction fail-open via numeric-range bound (GHSA-39q2-5h5r-39p7 / CVE-2026-84897, medium): IsMessageAllowedServer() applies no direction check to the key-exchange message range — after the server processes the client's KEXINIT nothing sets handshake->expectMsgId, so the expectation branch exits without a verdict and falls through to a numeric bound admitting every message id 30–34, i.e. server-to-client KEX_DH_GEX_GROUP (31) and KEX_DH_GEX_REPLY (33) from an unauthenticated client. State-machine axis for protocol audits: when the "what message do I expect next" register is unset, does the fallback deny or does it fall to a range check? A numeric range used as an expectation fallback is a standing accept surface — enumerate unset-expectation states in any handshake parser and probe out-of-direction messages by raw id.
  • forwarded-tcpip channel open skips the forwarding authorization gate (GHSA-cqr9-f685-gr3w / CVE-2026-81535, medium, --enable-fwd builds): DoChannelOpen() gates only direct-tcpip opens with the forwarding policy callback — forwarded-tcpip opens are admitted with no authorization check and no count cap (unbounded per-channel buffers), and the client side never checks a forwarded-tcpip open against the forwards it registered via tcpip-forward as RFC 4254 §7.2 requires, so a malicious server can open forwarding channels for addresses/ports the client never requested. Classic sibling-variant parity miss (the gated sibling is direct-tcpip; the ungated sibling is its reverse direction) plus a missing client-side registration cross-check — on port-forwarding-capable SSH stacks, test both channel-open spellings against the policy callback and test server-initiated forwards the client never requested.
  • Windows wolfSSHd login-token poisoning across connections (GHSA-36jf-xmwg-5wp8 / CVE-2026-83540, high, 1.4.15–1.5.0 Windows builds): the Windows logon token acquired for one authenticated connection is not released before a token is acquired for the next — a less-privileged user with any valid account can force subsequent sessions to run as a previously authenticated more-privileged user. Per-connection-credential-lifecycle axis: shared/static holders of auth tokens across connection boundaries turn any prior high-priv login on the same daemon into a contamination source; on Windows embedded-SSH targets (appliances, IoT management), auth one low-priv account then test whether a later session inherits the earlier token's SID.

Tracked from the same wave without publication: wstrncat() size-t underflow one-null-byte stack write via crafted SFTP path (GHSA-4ff8-whrv-3wcm, authenticated, memory-safety class). Cross-reference: the negotiated-vs-declared leg is the SSH twin of this page's MsQuic hostname-check and Xray-core empty-ServerName legs — three stacks, one week, same missing-comparison shape, different protocol layer.

October 8 18:3xZ follow-up: GnuTLS 3.8.13 hostname-verification bypass and wolfSSL name-constraint regression — the missing-comparison family keeps collecting stacks

  • GnuTLS v3.8.13 CommonName-fallback bypass (GHSA-2j2x-fffq-ff4q / CVE-2026-88647, + GHSA-9mfx-g534-q3pc / CVE-2026-95210 accepting certificates with invalid extensions, + GHSA-prfj-h7xq-vv26 / CVE-2026-95184 legitimate-cert rejection twin): a crafted certificate circumvents the CN fallback hostname-verification path → on-path eavesdrop. This is the fourth week of the same shape across stacks (wolfSSH curve-id GetSkip, MsQuic hostname check, Xray empty ServerName, this page's own legs): when SAN is absent, the fallback comparison itself is the security check — fuzz SAN-absent + CN-mismatch certificate shapes at any TLS client whose stack you can reach on-path. The accept-invalid-extensions leg and the reject-leg are the pair to run together: a client that accepts malformed extensions may carry attacker-controlled data past checks that assume well-formedness. Fix-band fingerprint: v3.8.13-era gnutls in TLS-terminating clients (proxies, mail/DAP connectors — libsasl2 genealogy again).
  • wolfSSL 5.9.1/5.9.2 ConfirmNameConstraints() regression (GHSA-vf9w-2hh8-xxhh / CVE-2026-95208): crafted CA certs make wolfSSL clients incorrectly reject SAN-less valid certificates — DoS-flavored, but the operator read is name-constraint evaluation is being touched in this band: the security-question twin (do name constraints actually narrow acceptance in 5.9.x?) stays on the battery for embedded-TLS targets, tested with your own two-CA lab (constraint-satisfying vs constraint-violating canary leaves).
  • Validation stays own-on-path harness + own CA trees; never MITM live targets.

October 13 follow-up: IBM DataStage on Cloud Pak for Data — session adapter auto-attaches the IAM bearer across an SDK TLS leg a forged certificate defeats (CVE-2026-84418 / GHSA-528j-3v52-48qw, high 7.4)

The vendor description is unusually precise about the mechanism: a MITM attacker presents a forged TLS certificate, intercepts the client-side SDK connection, and captures the IAM bearer Authorization header that the session adapter attaches automatically — the captured token grants full platform-scope tenant API access (read/manipulate DataStage projects, flows, assets, pipeline definitions). This is the platform-stack twin of the Cockpit worker-token leg above: the credential theft happens at the client construction site, not at the token's own endpoint.

Operator axes:

  1. Auto-attaching request adapters are token-leak amplifiers. Find where the SDK/client builds its HTTP session (grep for auth/interceptor/adapter classes that inject Authorization), then check what cert-validation posture that client has. If verification is default-off, per-request configurable, or delegated to a platform CA bundle the integrator can override, every call through that adapter is stealable from a network position — no second bug needed.
  2. Token scope is the severity multiplier. The advisory states the captured bearer is platform-scope, not call-scope: on Cloud Pak-style stacks (CP4D, OpenShift-adjacent IAM), a session token typically spans every microservice behind the platform proxy. Test read scope by replaying the captured token against 2–3 sibling service APIs in your own lab deployment; report "bearer captures = full tenant API surface" only after you've enumerated it.
  3. Cloud Pak / CP4D fingerprint: version 5.4.0.0 named here; the same IAM bearer + per-service SDK pattern applies across Cloud Pak products — on an authorized CP4D engagement, sweep every product SDK's client-construction site for cert-validation posture the same way. Validation boundary: own lab deployment, own on-path harness, synthetic tokens only; never intercept live platform traffic.

October 9 follow-up: sequoia-openpgp key-flag inference lets any subkey be bound and signatures forged (GHSA-g33h-rrj9-75qv / CVE-2026-42784, high)

sequoia-openpgp infers key flags for older certificates when the Key Flags subpacket is missing — and the inferred capability disagrees with what other verifiers assume. The consequence published in the advisory: the inference path lets an attacker bypass the back-signature check, bind an arbitrary subkey to their own certificate, and forge signatures with complete integrity compromise. Fourth member of this page's field-identity family's absent-field/permissive-inference branch (after the BC MLS credential, PKIX index-zero, and BCEL self-declared-name legs): when a capability-bearing field is absent, the library's default guess becomes the security policy, and verifier-to-verifier disagreement about the guess is itself the vulnerability.

Operator reading:

  • Cross-verifier capability-inference differential: for any format with optional capability fields (PGP key flags, X.509 keyUsage, JWT use/kid, SSH authorized_keys options), run the same crafted artifact (capability-field-absent variants) through two independent verifiers (e.g. sequoia vs GnuPG vs KBX-era parsers) and diff the accepted-capability verdicts. Where verifier A signs/verifies and verifier B accepts the binding, whoever trusts B is deceived by what A emitted. This extends the October 2 BC PKIXCertPathReviewer two-verifier-disagreement rule from name constraints to capability inference.
  • Back-signature / subkey-binding probe (lab, synthetic keys): generate two disposable PGP certs, craft a subkey binding on an old-shape cert without a Key Flags subpacket, and check whether the target library accepts the binding without the self-signature the policy requires. Forged-signature proof should mark only a canary message; never sign anything resembling real correspondence or code.
  • Fix fingerprint: the correction is in flag-inference code for pre-Key-Flags-era certs, so legacy-format fixtures (very old key generations) are the trigger shape — modern-key-only test corpora miss this class entirely. Same lesson as the Sept 15 one-canonical-form theme: fuzz the legacy representation, not just the current one.