# proto-file: third_party/java_src/jscomp/java/com/google/javascript/jscomp/conformance.proto
# proto-message: ConformanceConfig

# Conformance users:
#
# DO NOT COPY PASTE THESE RULES. If you do, changes to Closure can break your
# build and you also won't get new or improved rules. Instead use this file in
# your project and extend the rules to disable them or to add their allowlists.

### Platform restrictions ###

requirement: {
  rule_id: "closure:callee"
  type: BANNED_PROPERTY
  error_message: "Arguments.prototype.callee is not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#callee"

  value: "Arguments.prototype.callee"

  allowlist_regexp: ".+/closure/goog/debug/"  # legacy stack trace support, etc
  # TODO(mlourenco): Fix this? Not sure if possible or not.
  allowlist_regexp: ".+/closure/goog/testing/stacktrace.js"
}

requirement: {
  rule_id: "closure:throwOfNonErrorTypes"
  type: CUSTOM
  java_class: "com.google.javascript.jscomp.ConformanceRules$BanThrowOfNonErrorTypes"
  error_message: "Only Error or Error subclass objects may be thrown. See https://google.github.io/closure-library/develop/conformance_rules.html#throwOfNonErrorTypes"
  # TODO(user): Violation occurs in code generated by Emscripten.
  allowlist_regexp: ".+_wasm_js_library_generated.js"
  allowlist_regexp: ".+/closure/goog/storage/"  # throws numbers as part of its api
  allowlist_regexp: ".+/closure/goog/testing/mock.js"  # throws Object in $recordAndThrow
}

requirement: {
  rule_id: "closure:globalVars"
  type: CUSTOM
  java_class: "com.google.javascript.jscomp.ConformanceRules$BanGlobalVars"
  error_message: "Global declarations are not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#globalVars"
  allowlist_regexp: ".+/closure/goog/base.js"  # global 'goog'
  allowlist_regexp: ".+/closure/goog/labs/testing/"  # global matchers, etc
  allowlist_regexp: ".+/closure/goog/locale/locale.js"  # dumb api
  allowlist_regexp: ".+/closure/goog/testing/"  # global assert methods, etc
  allowlist_regexp: ".+/closure/goog/tweak/testhelpers.js"  # global values
  allowlist_regexp: "^Post-"  # injected '_ModuleManager_initialize'

  # Allowlist for global names
  value: "CLOSURE_DEFINES"  # Closure Compiler requires this to be a global var
  value: "CLOSURE_UNCOMPILED_DEFINES"  # Closure Compiler requires this to be a global var
  value: "CLOSURE_NO_DEPS"  # Closure Compiler requires this to be a global var
}

requirement: {
  rule_id: "closure:unknownThis"
  type: CUSTOM
  java_class: "com.google.javascript.jscomp.ConformanceRules$BanUnknownThis"
  error_message: "References to \"this\" that are typed as \"unknown\" are not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#unknownThis"

  allowlist_regexp: ".+/closure/goog/base.js"
  allowlist_regexp: ".+/closure/goog/debug/errorhandler.js"
  allowlist_regexp: ".+/closure/goog/editor/plugins/linkbubble.js"
  allowlist_regexp: ".+/closure/goog/editor/plugins/linkdialogplugin.js"
  allowlist_regexp: ".+/closure/goog/functions/functions.js"
  allowlist_regexp: ".+/closure/goog/memoize/memoize.js"
  allowlist_regexp: ".+/closure/goog/pubsub/pubsub.js"
  allowlist_regexp: ".+/closure/goog/testing/"
  allowlist_regexp: ".+/closure/goog/ui/editor/bubble.js"
  allowlist_regexp: ".+/closure/goog/ui/editor/toolbarcontroller.js"
  # TODO(user): Violation occurs in code generated by Emscripten.
  allowlist_regexp: ".+_wasm_js_library_generated.js"
}

### Browser tech requirements ###

# This requirement is somewhat Google-specific: open-source Closure users that
# don't use GAPI could reasonably ignore it depending on how they do messaging
# in their app.
requirement: {
  rule_id: "closure:postMessage"
  type: BANNED_PROPERTY_CALL
  error_message: "Window.prototype.postMessage is not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#postMessage"

  value: "Window.prototype.postMessage"

  # Known-safe common infrastructure.
  allowlist_regexp: ".+/closure/goog/async/nexttick.js"
  allowlist_regexp: ".+/closure/goog/net/xpc/nativemessagingtransport.js"
  # TODO(user): make sure this gets security reviewed (b/29333525).
  allowlist_regexp: ".+/closure/goog/messaging/portchannel.js"
}

### Security: forbid DOM properties and functions which can cause XSS ###

# These are properties and functions which might have safe wrappers under
# goog.dom.safe. Two groups: properties and functions which accept
# HTML/CSS/script-as-string, properties and function which accept URLs.

#### DOM properties and functions which accept HTML/CSS/script-as-string #####

requirement: {
  rule_id: 'closure:eval'
  # TODO(jakubvrana): Change to BANNED_NAME_CALL after cl/154708486 lands.
  type: BANNED_NAME
  error_message: 'eval is not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#eval'

  value: 'eval'
  value: 'execScript'
  value: 'goog.globalEval'

  allowlist_regexp: '.+/closure/goog/base.js' # goog.module loading in uncompiled code.
  allowlist_regexp: '.+/closure/goog/goog.js' # Forwards goog.globalEval
  allowlist_regexp: '.+/closure/goog/debug/errorhandler.js' # wraps setTimeout and similar functions
  allowlist_regexp: '.+/closure/goog/json/json.js' # used in goog.json.parse
  allowlist_regexp: '.+/closure/goog/module/loader.js'
  allowlist_regexp: '.+/closure/goog/module/moduleloader.js'
}

requirement: {
  rule_id: 'closure:windowEval'
  type: BANNED_PROPERTY_CALL
  error_message: 'window.eval is not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#eval'

  value: 'Window.prototype.eval'
  value: 'Window.prototype.execScript'

  allowlist_regexp: '.+/closure/goog/base.js'
  # TODO(jakubvrana): To be investigated.
  allowlist_regexp: '.+/closure/goog/net/xpc/nixtransport.js'
}

requirement: {
  rule_id: 'closure:stringFunctionDefinition'
  type: RESTRICTED_NAME_CALL
  error_message: 'Function, setTimeout, setInterval and requestAnimationFrame are not allowed with string argument. See https://google.github.io/closure-library/develop/conformance_rules.html#eval'

  value: 'Function:function()'
  value: 'setTimeout:function(Function, ...?)'
  value: 'setInterval:function(Function, ...?)'
  value: 'requestAnimationFrame:function(Function, ...?)'
}

requirement: {
  rule_id: 'closure:windowStringFunctionDefinition'
  type: RESTRICTED_METHOD_CALL
  error_message: 'window.setTimeout, setInterval and requestAnimationFrame are not allowed with string argument. See https://google.github.io/closure-library/develop/conformance_rules.html#eval'

  value: 'Window.prototype.setTimeout:function(Function, ...?)'
  value: 'Window.prototype.setInterval:function(Function, ...?)'
  value: 'Window.prototype.requestAnimationFrame:function(Function, ...?)'
}

requirement: {
  rule_id: 'closure:innerHtml'
  type: BANNED_PROPERTY_NON_CONSTANT_WRITE
  error_message: 'Assignment to Element.prototype.innerHTML is not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#innerHtml'

  value: 'Element.prototype.innerHTML'

  # Safe wrapper for this property.
  allowlist_regexp: '.+/closure/goog/dom/safe.js'

  # Safe DOM Tree Processor and HTML sanitizer, which use it safely in order to
  # have the browser parse an HTML string using an inert DOM.
  allowlist_regexp: '.+/closure/goog/html/sanitizer/htmlsanitizer.js'
  allowlist_regexp: '.+/closure/goog/html/sanitizer/safedomtreeprocessor.js'
  # Safely used in goog.string.unescapeEntitiesUsingDom_; the string assigned to
  # innerHTML is a single HTML entity.
  allowlist_regexp: '.+/closure/goog/string/string.js'
  # goog.soy.renderElement and renderAsElement.  Safe if used with Strict Soy
  # templates.
  allowlist_regexp: '.+/closure/goog/soy/soy.js'
  allowlist_regexp: '.+/closure/goog/dom/browserrange/ierange.js'
  allowlist_regexp: '.+/closure/goog/editor/'
  allowlist_regexp: '.+/closure/goog/style/style.js'
  allowlist_regexp: '.+/closure/goog/testing/'
}

requirement: {
  rule_id: 'closure:outerHtml'
  type: BANNED_PROPERTY_NON_CONSTANT_WRITE
  error_message: 'Assignment to Element.prototype.outerHTML is not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#innerHtml'

  value: 'Element.prototype.outerHTML'

  # Safe wrapper for this property.
  allowlist_regexp: '.+/closure/goog/dom/safe.js'
  allowlist_regexp: '.+/closure/goog/editor/'
}

requirement: {
  rule_id: 'closure:documentWrite'
  type: BANNED_PROPERTY
  error_message: 'Using Document.prototype.write is not allowed. Use goog.dom.safe.documentWrite instead. See https://google.github.io/closure-library/develop/conformance_rules.html#documentWrite.'

  value: 'Document.prototype.write'
  value: 'Document.prototype.writeln'

  # These are safe.
  allowlist_regexp: '.+/closure/goog/async/nexttick.js'
  allowlist_regexp: '.+/closure/goog/base.js'
  allowlist_regexp: '.+/closure/goog/dom/safe.js'
  # TODO(jakubvrana): These need to be refactored.
  allowlist_regexp: '.+/closure/goog/editor/icontent.js'
  allowlist_regexp: '.+/closure/goog/testing/'
}

requirement: {
  rule_id: "closure:untypedScript"
  type: CUSTOM
  java_class: "com.google.javascript.jscomp.ConformanceRules$BanCreateElement"
  error_message: "Use goog.dom functions with goog.dom.TagName.SCRIPT to create <script> elements. See https://google.github.io/closure-library/develop/conformance_rules.html#untypedElements"

  value: "script"

  allowlist_regexp: ".+/closure/goog/base.js"
}

requirement: {
  rule_id: "closure:untypedIframe"
  type: CUSTOM
  java_class: "com.google.javascript.jscomp.ConformanceRules$BanCreateElement"
  error_message: "Use goog.dom functions with goog.dom.TagName.IFRAME to create <iframe> elements. See https://google.github.io/closure-library/develop/conformance_rules.html#untypedElements"

  value: "iframe"

  allowlist_regexp: ".+/closure/goog/async/nexttick.js"
}

requirement: {
  rule_id: "closure:untypedFrame"
  type: CUSTOM
  java_class: "com.google.javascript.jscomp.ConformanceRules$BanCreateElement"
  error_message: "Use goog.dom functions with goog.dom.TagName.FRAME to create <frame> elements. See https://google.github.io/closure-library/develop/conformance_rules.html#untypedElements"

  value: "frame"
}

requirement: {
  rule_id: "closure:untypedObject"
  type: CUSTOM
  java_class: "com.google.javascript.jscomp.ConformanceRules$BanCreateElement"
  error_message: "Use goog.dom functions with goog.dom.TagName.OBJECT to create <object> elements. See https://google.github.io/closure-library/develop/conformance_rules.html#untypedElements"

  value: "object"
}

requirement: {
  rule_id: "closure:untypedEmbed"
  type: CUSTOM
  java_class: "com.google.javascript.jscomp.ConformanceRules$BanCreateElement"
  error_message: "Use goog.dom functions with goog.dom.TagName.EMBED to create <embed> elements. See https://google.github.io/closure-library/develop/conformance_rules.html#untypedElements"

  value: "embed"
}

requirement: {
  rule_id: 'closure:scriptContentProperty'
  type: BANNED_PROPERTY_WRITE
  error_message: 'Setting content of <script> and then appending it to the document has the same effect as calling eval(). See https://google.github.io/closure-library/develop/conformance_rules.html#scriptContent'
  # We ban untyped script creation by closure:untypedScript.
  report_loose_type_violations: false

  value: 'HTMLScriptElement.prototype.innerHTML'
  value: 'HTMLScriptElement.prototype.text'
  value: 'HTMLScriptElement.prototype.textContent'

  allowlist_regexp: '.+/closure/goog/base.js'
  allowlist_regexp: '.+/closure/goog/dom/safe.js'
}

requirement: {
  rule_id: 'closure:scriptContentMethod'
  type: BANNED_PROPERTY
  error_message: 'Setting content of <script> and then appending it to the document has the same effect as calling eval(). See https://google.github.io/closure-library/develop/conformance_rules.html#scriptContent'
  # We ban untyped script creation by closure:untypedScript.
  report_loose_type_violations: false

  value: 'HTMLScriptElement.prototype.appendChild'

  allowlist_regexp: '.+/closure/goog/base.js'
}

#### DOM properties and functions which accept URLs ####

# One rule per property name that exists for several types (e.g. href).
# Property names that exist for a single type (e.g. manifest) all
# share a single rule.
# Types with several dangerous properties and functions have their own rule
# (e.g. Location). This rule does not include any of its properties which are
# shared with other types (e.g. Location.prototype.href).
#
# For property names that exist on several types (e.g. href), the matching
# is done for their shared super type, even if the super type itself does not
# have the property. For example, Element does not have the href property, but
# many of its subtypes have. It's also necessary to match on Element for
# properties that exist on Element's subtypes because document.createElement()
# returns Element; matching on its subtypes only would miss many writes to the
# property.

# TODO(mlourenco): Create locationType rule banning protocol, assign()
# and replace() of Location.

# TODO(mlourenco): Move to "hrefProperty".
requirement: {
  rule_id: 'closure:locationHref'
  type: BANNED_PROPERTY_NON_CONSTANT_WRITE
  error_message: 'Assignment to Location.prototype.href is not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#location'

  value: 'Location.prototype.href'

  allowlist_regexp: '.+/closure/goog/dom/safe.js'

  # The following allowlist entries are due to usages of .href that still
  # need to be refactored or reviewed. See http://b/12014412.
  allowlist_regexp: '.+/closure/goog/history/history.js'
}

# TODO(mlourenco): Rename to "locationProperty". Add Document.location to it.
requirement: {
  rule_id: 'closure:location'
  type: BANNED_PROPERTY_NON_CONSTANT_WRITE
  error_message: 'Assignment to Window.prototype.location is not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#location'

  value: 'Window.prototype.location'
}

# TODO(user): Rename hrefProperty.
requirement: {
  rule_id: 'closure:href'
  type: BANNED_PROPERTY_NON_CONSTANT_WRITE
  error_message: 'Assignment to .href property of Anchor, Link, etc elements, is not allowed. See https://google.github.io/closure-library/develop/conformance_rules.html#href'

  # Many subtypes of Element have an href property.
  value: 'Element.prototype.href'
  # These are not subtypes of Element.
  value: 'StyleSheet.prototype.href'
  value: 'CSSImportRule.prototype.href'

  # Safe wrapper for this property.
  allowlist_regexp: '.+/closure/goog/dom/safe.js'
  # The following allowlist entries are due to usages of .href that still
  # need to be refactored or reviewed. See http://b/12014412.
  allowlist_regexp: '.+/closure/goog/editor/plugins/linkdialogplugin.js'
  allowlist_regexp: '.+/closure/goog/testing/testrunner.js'
  # This use has previously been refactored away, but had to be rolled
  # back due to breakages in gmail, see http://b/13727806.
  # This use may actually be safe because it only assigns to .href in
  # the context of a contenteditable. To be further reviewed.
  allowlist_regexp: '.+/closure/goog/editor/link.js'
}

# TODO(mlourenco): Move src to "srcProperty", others to "otherProperties". Ban
# "src" and other properties at "Element", so that elements returned by
# document.createElement() are captured.
requirement: {
  rule_id: "closure:trustedResourceUrlProperties"
  type: BANNED_PROPERTY_NON_CONSTANT_WRITE
  error_message: "Assignment to property requires a TrustedResourceUrl via goog.dom.safe. See https://google.github.io/closure-library/develop/conformance_rules.html#trustedResourceUrl"
  report_loose_type_violations: false

  # Properties which can only be assigned to from a TrustedResourceUrl.
  value: "HTMLElement.prototype.manifest"
  value: 'HTMLEmbedElement.prototype.src'
  value: 'HTMLFrameElement.prototype.src'
  value: 'HTMLIFrameElement.prototype.src'
  # For HTMLLinkElement both href and rel have to be assigned at the same time.
  value: "HTMLLinkElement.prototype.rel"
  # TODO(mlourenco): We probably want an "objectType" rule instead since
  # there are a bunch of dangerous properties.
  value: "HTMLObjectElement.prototype.data"
  value: 'HTMLScriptElement.prototype.src'
  # TODO(mlourenco): Ban other dangerous properties (archive, classid, etc).

  # Closure's debug loader.
  allowlist_regexp: '.+/closure/goog/base.js'
  # Safe wrapper for this property.
  allowlist_regexp: ".+/closure/goog/dom/safe.js"
  # The following allowlist entries are due to assignments from string that
  # still need to be refactored or reviewed. See http://b/12014412.
  allowlist_regexp: '.+/closure/goog/net/crossdomainrpc.js'
  allowlist_regexp: '.+/closure/goog/net/xpc/'
  allowlist_regexp: '.+/closure/goog/testing/multitestrunner.js'
  allowlist_regexp: '.+/closure/goog/ui/dragdropdetector.js'
}

requirement: {
  rule_id: "closure:createDom"
  type: CUSTOM
  java_class: "com.google.javascript.jscomp.ConformanceRules$BanCreateDom"
  error_message: "Assigning a string to a dangerous property via createDom is forbidden. See https://google.github.io/closure-library/develop/conformance_rules.html#createDom"

  value: "embed.src"
  value: "frame.src"
  value: "html.manifest"
  value: "iframe.src"
  value: "object.data"
  value: "script.src"
  value: "script.text"
  value: "script.textContent"
  value: "track.src"
  value: '*.href'
  value: '*.innerHTML'
  value: '*.outerHTML'

  allowlist_regexp: ".+/closure/tweak/tweakui.js"  # False positive - missing type on containerNodeName. MOE:strip_line
  allowlist_regexp: '.+/closure/goog/tweak/tweakui.js' # False positive - missing type on containerNodeName.

  # TODO(jakubvrana): Ban this.
  allowlist_regexp: '.+/closure/goog/ui/abstractspellchecker.js'
}

#### Closure functions which use goog.html.legacyconversions ####

# These are functions which accept a string and then use
# goog.html.legacyconversions to convert the string into SafeHtml. They
# are not XSS-safe.
#
# These rules allow projects to have compile-time errors for legacyconversions
# functions and to progressively move away from them by using the allowlist.

