Files
react/packages/react-dom/src/server/DOMMarkupOperations.js
T
Sebastian Markbåge 103378b1ea Warn for javascript: URLs in DOM sinks (#15047)
* Prevent javascript protocol URLs

* Just warn when disableJavaScriptURLs is false

This avoids a breaking change.

* Allow framesets

* Allow <html> to be used in integration tests

Full document renders requires server rendering so the client path
just uses the hydration path in this case to simplify writing these tests.

* Detect leading and intermediate characters and test mixed case

These are considered valid javascript urls by browser so they must be
included in the filter.

This is an exact match according to the spec but maybe we should include
a super set to be safer?

* Test updates to ensure we have coverage there too

* Fix toString invocation and Flow types

Right now we invoke toString twice when we hydrate (three times
with the flag off). Ideally we should only do it once even in this case
but the code structure doesn't really allow for that right now.

* s/itRejects/itRejectsRendering

* Dedupe warning and add the unsafe URL to the warning message

* Add test that fails if g is added to the sanitizer

This only affects the prod version since the warning is deduped anyway.

* Fix prod test
2019-03-11 16:39:49 -07:00

90 lines
2.3 KiB
JavaScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import {
ID_ATTRIBUTE_NAME,
ROOT_ATTRIBUTE_NAME,
BOOLEAN,
OVERLOADED_BOOLEAN,
getPropertyInfo,
isAttributeNameSafe,
shouldIgnoreAttribute,
shouldRemoveAttribute,
} from '../shared/DOMProperty';
import sanitizeURL from '../shared/sanitizeURL';
import quoteAttributeValueForBrowser from './quoteAttributeValueForBrowser';
/**
* Operations for dealing with DOM properties.
*/
/**
* Creates markup for the ID property.
*
* @param {string} id Unescaped ID.
* @return {string} Markup string.
*/
export function createMarkupForID(id: string): string {
return ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id);
}
export function createMarkupForRoot(): string {
return ROOT_ATTRIBUTE_NAME + '=""';
}
/**
* Creates markup for a property.
*
* @param {string} name
* @param {*} value
* @return {?string} Markup string, or null if the property was invalid.
*/
export function createMarkupForProperty(name: string, value: mixed): string {
const propertyInfo = getPropertyInfo(name);
if (name !== 'style' && shouldIgnoreAttribute(name, propertyInfo, false)) {
return '';
}
if (shouldRemoveAttribute(name, value, propertyInfo, false)) {
return '';
}
if (propertyInfo !== null) {
const attributeName = propertyInfo.attributeName;
const {type} = propertyInfo;
if (type === BOOLEAN || (type === OVERLOADED_BOOLEAN && value === true)) {
return attributeName + '=""';
} else {
if (propertyInfo.sanitizeURL) {
value = '' + (value: any);
sanitizeURL(value);
}
return attributeName + '=' + quoteAttributeValueForBrowser(value);
}
} else if (isAttributeNameSafe(name)) {
return name + '=' + quoteAttributeValueForBrowser(value);
}
return '';
}
/**
* Creates markup for a custom property.
*
* @param {string} name
* @param {*} value
* @return {string} Markup string, or empty string if the property was invalid.
*/
export function createMarkupForCustomAttribute(
name: string,
value: mixed,
): string {
if (!isAttributeNameSafe(name) || value == null) {
return '';
}
return name + '=' + quoteAttributeValueForBrowser(value);
}