Skip to content

feat(application): dissect every TLS record in a TCP segment, not only the first #2517

Closed

Description

@JarryShaw

On main, TLS dissects only the first record in a TCP segment. Every later record in the same segment is left as Raw, even though each one parses on its own. For example, TLS(ChangeCipherSpec + Alert) decodes the ChangeCipherSpec and leaves the Alert as 7 raw octets. This is routine on real traffic: frame 2 of Wireshark's tls13-rfc8446.pcap is a ServerHello followed by 465 octets of ChangeCipherSpec and encrypted records. Found by #2457's capture check.

Scope: dissect every complete record in the segment, with byte-exact round trips. Choose the representation (chained TLS layers, or a record list on one layer) per the conventions, and say which page decides it. A trailing partial record stays Raw (the #2441 reassembly limit).

Blocked: #2490's reorder is editing pcapkit/protocols/application/ssl.py. This unblocks when that lands, the same as #2514.

Activity

  1. added
    featPull requests that add a new capability (feat: subject prefix)
    blockedDeferred pending another issue or decision; see the last comment for what unblocks it
    on Nov 1, 2026
  2. moved this to Blocked in PyPCAPKiton Nov 1, 2026
  3. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor

    Unblocked: #2490's application reorder (#2522) touches only FTP, not ssl.py. Dispatched together with #2525, since both change how TLS.read handles records. #2514 waits for that PR.

  4. added
    wipWork in flight - a covering PR is open or an agent is actively on it
    and removed
    blockedDeferred pending another issue or decision; see the last comment for what unblocks it
    on Nov 1, 2026
  5. moved this from Blocked to WIP in PyPCAPKiton Nov 1, 2026
  6. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor

    Done locally with #2525 (397bac59f, 3ffbd98b9). It is held for the queue, with its Sonnet review running. Decisions:

    1. Representation: each whole record is its own TLS layer, chained as the previous record's payload. The code already models it that way: TLS.payload is documented as "a further record coalesced in the same buffer", HTTP/2 puts one frame in each layer, and SSLv2's tests chain records. A per-layer alias also stays one record's version. Options: (a) chained layers; (b) a record list on one layer, which changes Data_TLS and is breaking. Recommendation: (a), and write it onto protocol-family-grouping.rst once ruled.
    2. Chained records still try the SSLv2 fallback when their contents fail, because every record goes through the same parser. It is harmless and redundant. Options: leave it, or skip the fallback after the first record. Recommendation: leave it.

    Already settled: the warning order on a kept chain follows the owner's #2519 Q1 ruling. Follow-ups for DTLS (#2535) and HTTP/2 (#2536) are filed, each blocked on the PR that is editing its files.

  7. added
    needs: decisionWaiting on the maintainer to decide — not blocked by other work
    on Nov 1, 2026
  8. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor
    1. (a)
    2. leave it. but for malformed packets, use Raw instead of a fallback unknown protocol parser.
  9. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor

    Owner rulings, paraphrased: Q1 (a), chained layers. That is recorded, and the rule goes onto protocol-family-grouping.rst in this PR's fix round. Q2: leave the fallback, but a malformed record becomes Raw rather than going to a fallback parser.

    One check on Q2's second half, which can be read two ways. On this branch, a record that fails to decode already ends as Raw with an error, and TLS has no generic unknown-protocol parser. Its only fallback is the SSLv2 trial.

    • (A) A later record (not the first in the segment) that fails to decode goes straight to Raw, with no SSLv2 trial, because SSLv2 can only open a connection. The first record keeps its SSLv2 fallback.
    • (B) The rule is general: a payload its parser rejects becomes Raw, never a catch-all parser. That already holds, so nothing changes.

    Recommendation: (A). It goes into this PR's fix round, and becomes a no-op if you meant (B).

  10. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor

    (A)

  11. JarryShaw commented on Nov 1, 2026

    @JarryShaw
    OwnerAuthor

    Owner chose (A). A record after the first in a segment that fails to decode becomes Raw directly, with no SSLv2 trial, and the first record keeps its SSLv2 fallback. This goes into the fix round with the chained-layers rule for protocol-family-grouping.rst, once the local review lands. Every question here is answered.

  12. removed
    needs: decisionWaiting on the maintainer to decide — not blocked by other work
    on Nov 1, 2026
  13. removed
    wipWork in flight - a covering PR is open or an agent is actively on it
    on Nov 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    featPull requests that add a new capability (feat: subject prefix)

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions