Skip to content

URLs inside noscript bypass the proxy entirely #1120

Description

@jwrosewell

Every URL inside a <noscript> element reaches the visitor unrewritten. The proxy never sees it, so the browser contacts the third party directly.

The same URL inside and outside a noscript is treated differently. This input:

<noscript><iframe src="https://origin.example.com/tag"></iframe></noscript>
<iframe src="https://origin.example.com/tag"></iframe>

comes back as:

<noscript><iframe src="https://origin.example.com/tag"></iframe></noscript>
<iframe src="https://test.example.com/tag"></iframe>

Why it matters

noscript is where tag managers, analytics fallbacks and tracking pixels put their markup, so the bypass covers the requests a trusted server exists to carry. It fails silently. The page renders correctly and nothing is logged.

Cause

lol_html classifies noscript as raw text rather than markup, unconditionally and alongside style and iframe. The content therefore never becomes elements, so no attribute handler can see inside it. This is in the parser's tree builder simulator rather than in Trusted Server, so registering another element handler cannot reach it.

How it was reproduced

By adding a test to your own html_processor suite at 0f8b44dc0, using the existing create_test_config harness, and running the document above through StreamingPipeline. The output above is what the test observed. One of the two identical URLs was rewritten.

Suggested fix

Register a text!("noscript", ...) handler. A text node arrives in chunks and a URL can straddle two of them, so the node has to be accumulated and rewritten once complete, with earlier chunks held back rather than emitted, or the content is duplicated. The result must be emitted as HTML rather than as text, because it is markup the parser merely declined to parse, and escaping it would show the visitor the tags.

A branch is ready at fix/noscript-bypass, with a test covering both the rewriting and the escaping. It merges cleanly against main.

One dependency worth flagging. It sits on top of fix/origin-host-boundary, the branch offered for #1119, because both change the same rewriting path. Taking the boundary fix first makes this one a single commit.


Written with AI assistance and checked against the source at 0f8b44dc0. Worth a human review before acting on it.

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