Skip to content

Network policy: wildcard host matching not supported #663

Description

Summary

The network policy's AllowedHost::matches() performs exact string comparison, so neither global wildcards (host: "*") nor subdomain wildcards (host: "*.example.com") work. The wildcard characters are stored literally and compared against request hosts, which never matches.

Reproduction

  1. Load a WASM component with a policy granting network access to host: "*" (or host: "*.example.com")
  2. The component attempts an HTTP request to any host (e.g., https://www.sciencedaily.com/...)
  3. The request is blocked with:
    WARN wassette::http: HTTP request blocked by network policy
      uri=https://www.sciencedaily.com/...
      allowed_hosts={AllowedHost { scheme: None, host: "*" }}
    

Root cause

In crates/wassette/src/http.rs, AllowedHost::matches() does:

fn matches(&self, request_host: &str, request_scheme: Option<&str>) -> bool {
    if self.host != request_host {
        return false;
    }
    // ...
}

There is no special handling for wildcards — they are compared literally against the request host.

Expected behavior

Two wildcard patterns should be supported:

Pattern Matches Does not match
* any host —
*.example.com foo.example.com, bar.baz.example.com example.com (bare domain)

Suggested fix

fn matches(&self, request_host: &str, request_scheme: Option<&str>) -> bool {
    let host_matches = if self.host == "*" {
        true
    } else if let Some(suffix) = self.host.strip_prefix("*.") {
        request_host.ends_with(suffix)
            && request_host.len() > suffix.len()
            && request_host.as_bytes()[request_host.len() - suffix.len() - 1] == b'.'
    } else {
        self.host == request_host
    };

    if !host_matches {
        return false;
    }

    match (&self.scheme, request_scheme) {
        (Some(allowed_scheme), Some(req_scheme)) => allowed_scheme == req_scheme,
        _ => true,
    }
}

This issue was drafted with the help of an AI assistant (Claude).

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions