Repository: angular/angular
File: packages/core/src/sanitization/sanitization.ts (TypeScript)

Code before:
    throw new RuntimeError(RuntimeErrorCode.INVALID_EVENT_BINDING, errorMessage);
  }
}

export function validateAgainstEventAttributes(name: string) {
  if (name.toLowerCase().startsWith('on')) {
    const errorMessage =
      `Binding to event attribute '${name}' is disallowed for security reasons, ` +
      `please use (${name.slice(2)})=...`;
    throw new RuntimeError(RuntimeErrorCode.INVALID_EVENT_BINDING, errorMessage);
  }
}

function getSanitizer(): Sanitizer | null {
  const lView = getLView();
  return lView && lView[ENVIRONMENT].sanitizer;
}

/**
 * Validates that the attribute binding is safe to use.
 *
 * @param value The value of the attribute.
 * @param tagName The name of the tag.
 * @param attributeName The name of the attribute.
 */
export function ɵɵValidateAttribute(_value: any, tagName: string, attributeName: string): never {
  const errorMessage =
    `Binding to attribute '${attributeName}' of '${tagName}' is disallowed for security reasons, ` +
    `please use ${attributeName}="..."`;
  throw new RuntimeError(RuntimeErrorCode.INVALID_ATTRIBUTE_BINDING, errorMessage);
}


Review comment (security):
I applied the same approach used for iframes and `validateAgainstEventAttributes` handlers: throw a hard error when binding, ignoring the value. 

Not sure if we want to be more explicate and only throw or remove the attribute if the value is `href` or `xlink:href`. Similar to https://crsrc.org/c/third_party/blink/renderer/core/sanitizer/sanitizer.cc;l=770-775;drc=b3eb16372dcd3317d65e9e0265015e322494edcd



Code after:
    const errorMessage =
      `Binding to event property '${name}' is disallowed for security reasons, ` +
      `please use (${name.slice(2)})=...` +
      `\nIf '${name}' is a directive input, make sure the directive is imported by the` +
      ` current module.`;
    throw new RuntimeError(RuntimeErrorCode.INVALID_EVENT_BINDING, errorMessage);
  }
}

export function validateAgainstEventAttributes(name: string) {
  if (name.toLowerCase().startsWith('on')) {
    const errorMessage =
      `Binding to event attribute '${name}' is disallowed for security reasons, ` +
      `please use (${name.slice(2)})=...`;
    throw new RuntimeError(RuntimeErrorCode.INVALID_EVENT_BINDING, errorMessage);
  }
}

function getSanitizer(): Sanitizer | null {
  const lView = getLView();
  return lView && lView[ENVIRONMENT].sanitizer;
}

const attributeName: ReadonlySet<string> = new Set(['attributename']);

/**
 * @remarks Keep this in sync with DOM Security Schema.
 * @see [SECURITY_SCHEMA](../../../compiler/src/schema/dom_security_schema.ts)
 */
const SECURITY_SENSITIVE_ELEMENTS: Readonly<Record<string, ReadonlySet<string>>> = {
  'iframe': new Set([
    'sandbox',
    'allow',
    'allowfullscreen',
    'referrerpolicy',
    'csp',
    'fetchpriority',
  ]),
  'animate': attributeName,
  'set': attributeName,
  'animatemotion': attributeName,
  'animatetransform': attributeName,
};

/**
 * Validates that the attribute binding is safe to use.
 *
 * @param value The value of the attribute.
 * @param tagName The name of the tag.
 * @param attributeName The name of the attribute.
 */