Trail of Bits fixes mermaid-to-proverif, which read ProVerif's results backwards

1 month ago

Trail of Bits fixed mermaid-to-proverif, the trailmark skill that turns a Mermaid sequence diagram of a cryptographic protocol into a ProVerif model. It read ProVerif's reachability results backwards, and its forward-secrecy test leaked the long-term keys too early. Both are fixed in trailmark 0.12.1. https://github.com/trailofbits/skills/pull/367 https://github.com/trailofbits/skills

Ask about this presentation

Chapters

  1. 0:00Trail of Bits fixes mermaid-to-proverif, which read ProVerif's results backwards
  2. 0:26ProVerif prints is false when the event can happen
  3. 0:46Every other query rests on the reachability check
  4. 1:09The forward-secrecy test now leaks the keys after the sessions
  5. 1:28The skill's own example has a replay finding
  6. 1:50What changed in the trailmark plugin, and what stayed the same
Show transcript
  1. Trail of Bits has fixed mermaid-to-proverif, the skill that turns a Mermaid sequence diagram of a cryptographic protocol into a ProVerif model. It read the ProVerif reachability check backwards. So a correct model looked broken, and a broken model looked fine. If you have formally verified a protocol with this skill, those verdicts are worth a second look.

    Slide text
    github.com/trailofbits/skills trailmark plugin
    is false · model broken
    event reachable · model fine
    trailofbits/skills PR #367 · merged Oct 14, 2026
  2. ProVerif checks whether an event can happen by trying to prove it never does. So when the event is reachable, it prints "not event, is false." The skill told the model that false meant a structural bug. Now false is the good case, and true means the event never fires.

    Slide text
    mermaid-to-proverif · reachability ProVerif 2.05

    ProVerif prints "is false" when the event can happen

    query event(endR(pk_i, pk_r, k)).
    RESULT not event(endR(...)) is false.
    is false event fires: the expected result
    is true event never fires: the model is stuck
    PR #367 · mermaid-to-proverif/SKILL.md, step 5
  3. That check is the skill's first query. If the protocol's last step can't be reached, every secrecy and authentication result after it is meaningless. With the reading flipped, a stuck model passed that check. The skill, both of its reference files and its example all carried the backwards reading, five places in total.

    Slide text
    mermaid-to-proverif · reachability 5 places corrected

    Every secrecy and authentication result rests on the reachability check

    reachability passed
    model never ran its last step
    PR #367 · SKILL.md · references/proverif-syntax.md · references/security-properties.md
  4. The forward secrecy pattern had a second problem. It handed both long-term keys to the attacker at the very start, so the attacker could impersonate either side, and secrecy failed for every authenticated protocol. Now the keys leak after the sessions finish, and on the example both secrecy queries hold.

    Slide text
    mermaid-to-proverif · forward secrecy ProVerif 2.05

    The forward-secrecy test now leaks the long-term keys after the sessions

    before: keys leaked at the start
    new sk_I: skey; out(c, pk(sk_I)); out(c, sk_I);
    secrecy: is false for any authenticated protocol
    after: keys leaked in phase 1
    (phase 1; out(c, sk_I); out(c, sk_R))
    example's secrecy queries: is true
    PR #367 · references/security-properties.md, Forward Secrecy
  5. The example the skill teaches from had a finding of its own. Its handshake has no challenge from the responder, so replaying the first message completes another responder session, and the replay check fails. The weaker authentication property holds. The example now reports that replay as a real finding.

    Slide text
    mermaid-to-proverif · simple-handshake example ProVerif 2.05

    The skill's own handshake example lets a replayed first message start another session

    RESULT inj-event(endR(...)) ==> inj-event(beginI(...)) is false.
    weak, non-injective authentication: holds
    PR #367 · examples/simple-handshake/sample-output.pv, query Q3
  6. The models the skill writes are unchanged. What changed is how it reads ProVerif's answers, and how it tests forward secrecy. A new test keeps that guidance matched to ProVerif's output, and only runs ProVerif itself where it is installed. The update ships in the trailmark plugin, which loads in Claude Code and in Codex.

    Slide text
    github.com/trailofbits/skills trailmark plugin

    The guidance changed, and the generated models did not

    Same model logic, skill name and workflow. A new test checks the wording against ProVerif's output, and runs ProVerif itself only where it is installed.

    github.com/trailofbits/skills/pull/367
    PR #367 · tests/test_guidance.py

What happened in AI today, in your inbox

One short email each evening. Read it and you’re caught up.

Built with ❤️ in New York