Skip to content

Proposal: Simplify wasi-tls for Security and Forward Compatibility #13

@attackordie

Description

@attackordie

Proposal: Simplify wasi-tls for Security and Forward Compatibility

Executive Summary

This proposal recommends simplifying the wasi-tls API by:

  1. Supporting TLS 1.3 only (no TLS 1.2 fallback)
  2. Omitting session resumption (security over marginal performance)
  3. Excluding 0-RTT/early data (fundamental replay vulnerability)
  4. Removing suspension points (natural async evolution for Preview 3)

These changes would reduce the API surface by ~40%, eliminate entire classes of vulnerabilities, and ensure seamless evolution to WASI Preview 3's async model.

Background

The wasi-tls proposal is currently in Phase 1 and aims to provide high-level TLS functionality for WASI applications. As we move toward Phase 2, we have an opportunity to learn from industry experience and security research to create a more secure, maintainable API.

Rationale for Changes

1. TLS 1.3 Only

Current State of TLS Adoption:

  • 75.3% of top websites support TLS 1.3 (SSL Labs SSL Pulse, June 2025)
  • All major browsers have supported TLS 1.3 since 2018
  • All major cloud providers default to TLS 1.3

Security Benefits:

  • Eliminates protocol downgrade attacks entirely
  • Removes weak cipher suites (RC4, 3DES, SHA-1)
  • Mandatory perfect forward secrecy
  • 1-RTT handshake reduces attack window

Compatibility Impact:

  • Systems requiring TLS 1.2 are typically 5+ years old
  • Can use TLS termination proxies if needed
  • Aligns with industry deprecation timeline (many dropping TLS 1.2 in 2025)

With 75.3% adoption already achieved and growing, TLS 1.3 has reached critical mass for becoming the baseline standard.

2. Omit Session Resumption

Security Concerns:

  • Weakens forward secrecy by linking multiple connections
  • Complex key rotation requirements across distributed systems
  • Session ticket compromise affects all linked sessions

Limited Performance Benefit with TLS 1.3:

  • New connection: 1-RTT (~50-100ms)
  • With resumption: 1-RTT (same RTT, minor CPU savings)
  • Modern hardware makes CPU difference negligible (~2-5ms)

Recommendation: Can be added in a future version if real-world usage demonstrates need.

3. Exclude 0-RTT/Early Data

Critical Security Flaw - RFC 8446 Section 8.3:

"TLS does not provide any mechanism for guaranteeing that the early data is not replayed."

Industry Rejection:

  • Cloudflare: Disabled by default
  • Chrome: Not used for third-party sites
  • Safari: Completely disabled
  • Mozilla: Restricted to safe methods only

Attack Scenario:

1. Attacker captures 0-RTT: "POST /api/transfer?amount=1000"
2. Attacker replays packet multiple times
3. Server processes all replays (no replay protection)
4. Catastrophic consequences

4. Remove Suspension Points

Current Complexity:

// Complex state machine with suspension
flags server-suspension-points {
    client-hello,
    verify-client-identity,
    accepted,
}
// Multiple pause/resume states = deadlock potential

Simpler Alternative:

// Linear flow without suspension
resource server {
    new: static func(input, output) -> server;
    set-identity: func(identity) -> result;
    finish: func() -> result<connection>;
}

Proposed API Design

Core Principles

  • Security by default: No weak options available
  • Minimal surface: Essential features only
  • Forward compatible: Natural evolution to async
  • Type safe: Clear resource lifecycles

Simplified WIT Interface

package wasi:tls@0.1.0;

interface tls {
    use wasi:io/streams@0.2.0.{input-stream, output-stream};
    use wasi:io/poll@0.2.0.{pollable};
    
    /// TLS 1.3 only - no protocol version negotiation needed
    type cipher-suite = u16;  // Only AEAD suites
    
    /// Minimal error types
    enum error-code {
        handshake-failure,
        certificate-invalid,
        certificate-untrusted,
        certificate-expired,
        hostname-mismatch,
        internal-error,
        would-block,
    }
    
    /// Certificate for validation
    resource certificate {
        subject: func() -> string;
        issuer: func() -> string;
        verify-hostname: func(hostname: string) -> bool;
    }
    
    /// Private identity (certificate + key)
    resource private-identity {
        certificate: func() -> certificate;
    }
    
    /// Active connection
    resource connection {
        cipher-suite: func() -> cipher-suite;
        peer-certificate: func() -> option<certificate>;
        close: func() -> result<_, error-code>;
    }
    
    /// Client handshake
    resource client {
        new: static func(
            server-name: string,
            transport-input: input-stream,
            transport-output: output-stream,
        ) -> result<client, error-code>;
        
        set-alpn-protocols: func(protocols: list<string>) -> result;
        set-identity: func(identity: borrow<private-identity>) -> result;
        
        finish: func() -> result<client-result, error-code>;
        subscribe: func() -> pollable;  // Preview 2
        // finish: async func() -> result<client-result>;  // Preview 3
    }
    
    record client-result {
        connection: connection,
        input: input-stream,
        output: output-stream,
    }
    
    /// Server handshake
    resource server {
        new: static func(
            transport-input: input-stream,
            transport-output: output-stream,
        ) -> result<server, error-code>;
        
        set-identity: func(identity: borrow<private-identity>) -> result;
        set-alpn-protocols: func(protocols: list<string>) -> result;
        set-client-auth-required: func(required: bool) -> result;
        
        finish: func() -> result<server-result, error-code>;
        subscribe: func() -> pollable;  // Preview 2
        // finish: async func() -> result<server-result>;  // Preview 3
    }
    
    record server-result {
        connection: connection,
        input: input-stream,
        output: output-stream,
    }
}

WASI Preview 3 Compatibility

The design naturally evolves to async without breaking changes:

Preview 2 (Current):

let client = Client::new(server_name, input, output)?;
let pollable = client.subscribe();
poll::wait(&[pollable])?;
let result = client.finish()?;

Preview 3 (Future):

let client = Client::new(server_name, input, output)?;
let result = client.finish().await?;  // Natural async/await

No suspension points needed - the async runtime handles waiting naturally.

Implementation Considerations

For Advanced Use Cases

If specific advanced features are needed, they can be added as separate, optional interfaces:

// Optional: SNI inspection without full handshake
interface tls-sni-inspector {
    peek-sni: func(stream: input-stream) -> result<string>;
}

// Optional: Post-handshake authentication (RFC 8446 §4.6.2)
interface tls-post-handshake {
    request-client-cert: func(conn: connection) -> result<certificate>;
}

Migration Path for Existing Systems

For systems requiring TLS 1.2:

  1. Use edge/proxy for TLS termination
  2. Upgrade to TLS 1.3 (OpenSSL 1.1.1+ available since 2018)
  3. Use platform-specific TLS if legacy support required

Benefits Summary

Security Benefits

  • Eliminates replay attacks (no 0-RTT)
  • Prevents downgrade attacks (TLS 1.3 only)
  • Improves forward secrecy (no session linkage)
  • Reduces attack surface (~40% fewer code paths)

Simplicity Benefits

  • ~25 methods instead of ~50+
  • Linear control flow (no state machines)
  • Clear error handling (no suspension edge cases)
  • Easier testing (fewer state combinations)

Compatibility Benefits

  • Natural Preview 3 evolution (just add async)
  • No breaking changes needed for async
  • Aligns with modern platforms (Lambda, Workers, etc.)

Stakeholder Alignment

This proposal aligns with:

  • WASI Principles: "Start as MVP with bare minimum APIs"
  • Security Best Practices: Following Cloudflare, Google, Mozilla decisions
  • Industry Direction: TLS 1.2 deprecation timeline
  • .NET Requirements: Works with System.Net.Security.SslStream model

Next Steps

  1. Gather feedback on this simplified approach
  2. Update imports.md with the simplified WIT
  3. Create reference implementation demonstrating the API
  4. Document security rationale for omitted features

Conclusion

By focusing on TLS 1.3's core security benefits and omitting problematic features, we can deliver a wasi-tls API that is:

  • More secure (no replay vulnerabilities)
  • Simpler to implement (40% less code)
  • Easier to use (linear API flow)
  • Future-proof (natural async evolution)

The small trade-off in compatibility (affecting only 5+ year old systems) is worth the significant gains in security and maintainability.

References


This proposal is submitted for discussion as wasi-tls moves toward Phase 2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions