fix(tls): cap weak-cipher evidence vec at 64 with elision marker#195
Merged
Conversation
Add test_weak_cipher_evidence_capped_at_64_with_elision: builds a ClientHello with 65 distinct weak cipher IDs (all confirmed to match is_weak_cipher via NULL/ANON/EXPORT name check) and asserts the resulting finding's evidence vec is bounded at 65 entries — 64 cipher names plus a "(+1 more)" elision marker. Currently RED: the uncapped implementation produces 65 cipher-name entries and no elision marker, failing the last-entry elision check. Classification: LOW-SEVERITY HARDENING (CWE-405-adjacent but not CWE-405; bounded linear transient allocation, not asymmetric amplification).
…hardening) Cap the weak-cipher evidence collection to WEAK_CIPHER_EVIDENCE_CAP=64 entries. When the ClientHello offers more than 64 weak ciphers, append a single "(+N more)" elision marker as the 65th evidence entry instead of collecting all names. The total weak count is computed with a separate .count() pass (one extra scan of the cipher slice, bounded by MAX_RECORD_PAYLOAD=18,432), so the cap-plus-elision branch is O(n) in the cipher list length. Classification: LOW-SEVERITY HARDENING. Input is bounded upstream (MAX_RECORD_PAYLOAD=18,432 bytes → ≤9,216 cipher IDs), so the uncapped allocation was a bounded linear transient allocation, NOT asymmetric amplification. This does NOT meet CWE-405. The cap simply avoids a few-hundred-KB String allocation on crafted maximal inputs. Existing behavior for ≤64 weak ciphers is unchanged (no elision entry appended, output identical to before). Also applies rustfmt formatting to the failing test committed in the previous commit.
Zious11
added a commit
that referenced
this pull request
Jun 8, 2026
…positions (D-022) Cohort A (#100-#104) re-validated under DF-VALIDATION-001 (all 5 STILL-VALID). - #104 CLOSED: SNI control-byte summary for mixed control+non-ASCII (BC-TLS-037, PR #194 cf21168) - #102 CLOSED: cap weak-cipher evidence vec at 64 + elision; reclassified low-severity hardening NOT CWE-405/DoS (PR #195 153f225) - #100: FEATURE-MODE — breaks StreamHandler::on_data + ~22 emission sites; pending feature scope - #101: OPEN-DEBT — corpus-dependent FP/TP measurement; blocks #103 - #103: DEFERRED — wirerust-original size-symmetry discriminator; sequence with #101 Dependabot live; PR #193 (actions/checkout 6→6.0.2) pending disposition. develop_head updated: 2fe3440 → 153f225. Count-propagation sweep: develop_head updated in STATE.md frontmatter + session checkpoint. Old SHA 2fe3440 retained only in historical D-021 and DI-001 drift rows (immutable audit trail).
Zious11
added a commit
that referenced
this pull request
Jun 8, 2026
…gate (D-023) D-023: hybrid Claude+Gemini adversarial review of dependabot PR #193; both converged on SHA-pin verdict. Hallucination sweep: 2 Gemini fabrications discarded. Prior pass (D-021) was 3/8 complete; now 7/8 pinned (checkout, rust-cache, cargo-deny, semantic-pr + prior upload-artifact, download-artifact, gh-release). Action pin gate CI job added; CLAUDE.md policy documented. PR #196 → develop 77fd45f. PG-4 [codified]: dependabot tag→SHA gap now enforced by pin gate. ACTION-PIN-001: dtolnay/rust-toolchain exempt (intentional). develop_head: 153f225 → 77fd45f. Count-propagation sweep: develop_head updated in STATE.md only (single source of truth; no index files reference this SHA). Historical 153f225 cite in D-022 row retained (immutable audit trail — PR #195 merge commit).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
handle_client_helloinsrc/analyzer/tls.rsbuilt the weak-cipherevidenceVec without any upper bound. A crafted ClientHello advertising a large number of weak cipher suites caused a transient String allocation proportional to the count (up to several hundred KB). This PR caps the evidence Vec at 64 entries and appends a(+N more)elision marker when the cap is exceeded.Reclassification (explicit): Research confirmed this is LOW-SEVERITY HARDENING, NOT a DoS or CWE-405 issue. CWE-405 requires asymmetric amplification; this allocation is strictly linear and is already bounded by
MAX_RECORD_PAYLOAD = 18,432 bytes(~9,216 cipher IDs maximum). No security label has been applied.Problem
With a maximal weak-cipher ClientHello (~9,216 cipher IDs), the transient allocation was in the hundreds of KB before the finding was stored.
Fix
count()the weak ciphers, then.take(64)during collection — avoids materializing the full Vec.(+N more)entry preserves forensic transparency.MAX_MAP_ENTRIESidiom used elsewhere in the codebase.Architecture Changes
graph TD A[ClientHello parser] --> B[handle_client_hello] B --> C{weak ciphers present?} C -->|yes| D[count total_weak] D --> E[take up to 64 entries] E --> F{total_weak > 64?} F -->|yes| G[append elision marker] F -->|no| H[evidence Vec as-is] G --> I[push Finding] H --> I C -->|no| J[skip]Spec Traceability
flowchart LR BC102["BC-TLS-102\nWeak-cipher evidence unbounded"] --> AC102["AC-102\nEvidence capped at 64\n+ elision marker"] AC102 --> T1["test: overflow_weak_cipher_evidence_is_capped\n(red→green, TDD)"] T1 --> IMPL["src/analyzer/tls.rs\nWEAK_CIPHER_EVIDENCE_CAP = 64"]Test Evidence
477a6f3introduces the failing test;d22b9femakes it green.test_overflow_weak_cipher_evidence_is_cappedintests/tls_analyzer_tests.rs— constructs a synthetic ClientHello with 200 weak ciphers, assertsevidence.len() == 65(64 real + 1 elision marker), and verifies the marker format(+136 more).cargo test --all-targets).-D warnings.cargo fmt --checkpasses.Security Review
No new attack surface introduced. The fix reduces (not increases) the maximum transient allocation. No injection, auth, or input-validation concerns. OWASP Top 10 not applicable to this change.
Risk Assessment
handle_client_hello) in the TLS analyzerevidenceVec truncated at 64 entries + elision marker appendedDependency Graph
graph LR THIS["fix/weak-cipher-cap\n(this PR)"] --> DEVELOP["develop"]No upstream PR dependencies.
Pre-Merge Checklist
fix(tls): ...)Closes #102