diff --git a/packages/@glimmer-workspace/integration-tests/test/attributes-test.ts b/packages/@glimmer-workspace/integration-tests/test/attributes-test.ts index eef13f25c13..41067a4a7d7 100644 --- a/packages/@glimmer-workspace/integration-tests/test/attributes-test.ts +++ b/packages/@glimmer-workspace/integration-tests/test/attributes-test.ts @@ -144,6 +144,40 @@ export class AttributesTests extends RenderTest { this.assertStableNodes(); } + @test + 'button[formaction] is marked as unsafe'() { + // `formaction` overrides the owning form's `action` at submit time, so it + // is the same submission-URL sink as `
` and must reject + // `javascript:` URLs. Otherwise it is a drop-in bypass for the `action` + // sanitization. + this.render('
', { + foo: 'javascript:foo()', + }); + this.assertHTML('
'); + this.assertStableRerender(); + + this.rerender({ foo: 'http://foo.bar' }); + this.assertHTML('
'); + this.assertStableNodes(); + + this.rerender({ foo: 'javascript:foo()' }); + this.assertHTML('
'); + this.assertStableNodes(); + } + + @test + 'input[formaction] is marked as unsafe'() { + this.render('
', { + foo: 'javascript:foo()', + }); + this.assertHTML('
'); + this.assertStableRerender(); + + this.rerender({ foo: 'http://foo.bar' }); + this.assertHTML('
'); + this.assertStableNodes(); + } + @test 'triple curlies in attribute position'() { this.render('
Hello
', { diff --git a/packages/@glimmer/runtime/lib/dom/sanitized-values.ts b/packages/@glimmer/runtime/lib/dom/sanitized-values.ts index a5203749453..0ab723f357c 100644 --- a/packages/@glimmer/runtime/lib/dom/sanitized-values.ts +++ b/packages/@glimmer/runtime/lib/dom/sanitized-values.ts @@ -4,11 +4,19 @@ import { isSafeString, normalizeStringValue } from '../dom/normalize'; const badProtocols = ['javascript:', 'vbscript:']; -const badTags = ['A', 'BODY', 'LINK', 'IMG', 'IFRAME', 'BASE', 'FORM']; +// `BUTTON`/`INPUT` are included because a submit `