Skip to content

sidecar_traffic_routing: allowlist two Modal endpoints and block domain fronting - #1627

Closed
Lukas Bjarre (lbjarre) wants to merge 2 commits into
mainfrom
devin/1788959101-sidecar-domain-fronting
Closed

Lukas Bjarre (lbjarre) wants to merge 2 commits into
mainfrom
devin/1788959101-sidecar-domain-fronting

Conversation

@lbjarre

@lbjarre Lukas Bjarre (lbjarre) commented Sep 9, 2026 •

Copy link
Copy Markdown

Reworks the Sidecar MITM proxy example so it demonstrates (and actually enforces) protection against domain fronting.

The previous GitHub-based filter was bypassable: it only inspected flows whose SNI was exactly github.com, chose the upstream from that same SNI, and never bound SNI to the HTTP Host header. From inside the Sandbox, curl -H 'Host: github.com' https://www.github.com/<forbidden> (or a trailing-dot github.com.) reached forbidden paths with a 200.

Changes:

  • Two self-contained Web endpoints (allowed, blocked) deployed from the script via a web_app, following the pattern in sidecar_secrets_injection.py. Both sit on Modal's shared modal.run ingress, which routes purely on Host — a realistic fronting target (exfil/C2 shape) instead of a www subdomain.
  • mitmproxy addon is now a default-deny allowlist with an explicit SNI/Host bind:
    sni  = _canonical_host(flow.client_conn.sni)        # lowercase, strip trailing "."
    host = _canonical_host(flow.request.pretty_host)
    if not sni or host != sni:  -> 403  (fronting / missing SNI, fail closed)
    if host != ALLOWED_HOST:    -> 403  (not on allowlist)
    tls_clienthello also canonicalizes before selecting the upstream.
  • New "Block domain fronting" section at the bottom explaining the attack and running it (curl https://<allowed> -H 'Host: <blocked>'), expected output:
    GET allowed endpoint -> 200
    GET blocked endpoint -> 403
    GET allowed SNI + blocked Host -> 403
    

Verified end-to-end on Modal by Lukas Bjarre (@lbjarre) with an equivalent standalone draft (same addon logic, same three checks; all rows matched). This exact file passes ruff/py_compile but was not run on Modal from this session (no token secret available).

Type of Change

  • Example updates (Bug fixes, new features, etc.)

Monitoring Checklist

  • Example is configured for testing in the synthetic monitoring system, or lambda-test: false is provided in the example frontmatter and I have gotten approval from a maintainer
    • Example is tested by executing with modal run, or an alternative cmd is provided in the example frontmatter (e.g. cmd: ["modal", "serve"])
    • Example is tested by running the cmd with no arguments, or the args are provided in the example frontmatter
    • Example does not require third-party dependencies besides fastapi to be installed locally

Documentation Site Checklist

Content

  • Example is documented with comments throughout, in a Literate Programming style
  • All media assets for the example that are rendered in the documentation site page are retrieved from modal-cdn.com

Build Stability

  • Example pins all dependencies in container images
    • Example pins container images to a stable tag like v1, not a dynamic tag like latest
    • Example specifies a python_version for the base image, if it is used
    • Example pins all dependencies to at least SemVer minor version (mitmproxy==12.2.3, fastapi[standard]==0.139.2)
      • Example dependencies with version < 1 are pinned to patch version, ==0.y.z

Link to Devin session: https://modal.devinenterprise.com/sessions/01490ac54e144afb9a5b2c18c4ed8c08
Open in Devin Desktop: https://modal.devinenterprise.com/desktop/session/01490ac54e144afb9a5b2c18c4ed8c08?variant=devin


Devin Review

…in fronting

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or 'Devin Naquin (@devin)'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Devin Review

Comment thread 13_sandboxes/sidecar_traffic_routing.py
@devin-ai-integration

Copy link
Copy Markdown
Contributor

Superseded by https://github.com/modal-labs/modal/pull/57976 — the monorepo is the copybara source of truth for //examples, so this change needs to land there.

@lbjarre
Lukas Bjarre (lbjarre) deleted the devin/1788959101-sidecar-domain-fronting branch September 25, 2026 13:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant