{"action":"created","issue":{"url":"https://api.github.com/repos/whatwg/html/issues/3518","repository_url":"https://api.github.com/repos/whatwg/html","labels_url":"https://api.github.com/repos/whatwg/html/issues/3518/labels{/name}","comments_url":"https://api.github.com/repos/whatwg/html/issues/3518/comments","events_url":"https://api.github.com/repos/whatwg/html/issues/3518/events","html_url":"https://github.com/whatwg/html/issues/3518","id":301576285,"number":3518,"title":"Proposal: HTML passwordrules attribute","user":{"login":"dbates-wk","id":20798617,"avatar_url":"https://avatars3.githubusercontent.com/u/20798617?v=4","gravatar_id":"","url":"https://api.github.com/users/dbates-wk","html_url":"https://github.com/dbates-wk","followers_url":"https://api.github.com/users/dbates-wk/followers","following_url":"https://api.github.com/users/dbates-wk/following{/other_user}","gists_url":"https://api.github.com/users/dbates-wk/gists{/gist_id}","starred_url":"https://api.github.com/users/dbates-wk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dbates-wk/subscriptions","organizations_url":"https://api.github.com/users/dbates-wk/orgs","repos_url":"https://api.github.com/users/dbates-wk/repos","events_url":"https://api.github.com/users/dbates-wk/events{/privacy}","received_events_url":"https://api.github.com/users/dbates-wk/received_events","type":"User","site_admin":false},"labels":[{"id":255178143,"url":"https://api.github.com/repos/whatwg/html/labels/addition/proposal","name":"addition/proposal","color":"d4c5f9","default":false},{"id":328374126,"url":"https://api.github.com/repos/whatwg/html/labels/document%20conformance","name":"document conformance","color":"fad8c7","default":false},{"id":257427609,"url":"https://api.github.com/repos/whatwg/html/labels/needs%20implementer%20interest","name":"needs implementer interest","color":"5319e7","default":false},{"id":377132241,"url":"https://api.github.com/repos/whatwg/html/labels/security/privacy","name":"security/privacy","color":"0052cc","default":false},{"id":402537936,"url":"https://api.github.com/repos/whatwg/html/labels/topic:%20forms","name":"topic: forms","color":"009800","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":24,"created_at":"2018-03-01T22:02:50Z","updated_at":"2018-03-13T04:04:17Z","closed_at":null,"author_association":"NONE","body":"# HTML `passwordrules` attribute\r\n\r\n## Motivation\r\n\r\nSome user agents offer to generate random per-site passwords on behalf of the user. Safari has built-in support for this, and add-on password managers such as 1Password add this functionality. This feature improves user security by guaranteeing high-entropy passwords and avoiding reuse of the same password on multiple sites.\r\n\r\nOne challenge with this approach is that sites have different rules for valid passwords. Many sites require characters from specific sets to be present, or have other constraints. The best known solution is to have a generator rule that matches the password requirements of many sites, plus a curated list of per-site quirks for sites with unusual requirements.\r\n\r\nA better solution would be for the website to express its password requirements in machine-readable form, and in a format that is suited for use with a generation algorithm. While the `pattern` attribute allows expressing many value constraints, it's very hard to use it to drive a generator. It's also tricky to express many popular password constraints (such as a limit on the number of consecutive repeated characters) in a regexp.\r\n\r\n## Proposed Solution\r\n\r\nWe propose a new content attribute on the HTML input element called `passwordrules` and define a mini syntax for web authors to use to express their requirements (rules). We describe how a user agent will makes use of these rules and the minimum requirements for the user agent to honor these rules below.\r\n\r\n### Extensions to HTML\r\n\r\nWe propose the following new content attribute be added to the HTML input element:\r\n```\r\n\tpasswordrules\r\n```\r\n\r\n### Using the `passwordrules` attribute\r\n\r\nThe `passwordrules` attribute, when specified, describes the set of extra restrictions on the value of the element's `value` attribute that a user agent must consider when generating a password and performing [client-side form validation](#interaction-with-client-side-form-validation). Its value is a semicolon delimited string of one or more property/value pairs and has the form:\r\n\r\n```\r\nrequired: (<identifier> | <character-class>), ..., (<identifier> | <character-class>); allowed: (<identifier> | <character-class>), ..., (<identifier> | <character-class>); max-consecutive: <non-negative-integer>\r\n```\r\n\r\nAn `<identifier>` must case-insensitively match one of the following strings: `upper`, `lower`, `digit`, `special`, `ascii-printable`, and `unicode`. These identifiers correspond to the set of ASCII uppercase letters (A-Z), lowercase letters (a-z), digits (0-9), all other ASCII printable characters - including the space character - (-~!@#$%^&*_+=`|(){}[:;\"'<>,.? ]), all ASCII printable characters, and all Unicode characters, respectively.\r\n\r\nA `<character-class>` is a [custom characters class](#custom-character-classes).\r\n\r\nA `<non-negative-integer>` is a [valid non-negative integer](https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-non-negative-integer).\r\n\r\nThe [missing value default](https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#missing-value-default) for `passwordrules` is `allowed: ascii-printable`. There is no [invalid value default](https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#invalid-value-default).\r\n\r\nThe values of multiple ~~`required`/~~`allowed` properties are concatenated together and multiple `max-consecutive` properties behave as if a single `max-consecutive` property was specified whose value is the minimum of all `max-consecutive` properties. Duplicate property values are ignored. Specifying multiple character classes is equivalent to specifying one character class that represents the union of the characters in all character classes. Empty character classes are ignored. Properties without a value are ignored. The following examples illustrate the aforementioned equivalences:\r\n\r\n~~`required: upper; required: lower` <=> `required: upper, lower`~~\r\n*`allowed: upper; allowed: lower` <=> `allowed: upper, lower`*\r\n`max-consecutive: 4; max-consecutive: 2` <=> `max-consecutive: 2`\r\n`required: upper, lower, upper` <=> `required: upper, lower`\r\n`required: [abc], [def]` <=> `required: [abcdef]`\r\n`allowed: upper, []` <=> `allowed: upper`\r\n`required: ; allowed: upper` <=> `allowed: upper`\r\n\r\n***NOTE**: The expression `required: upper; required: lower` is NOT equivalent to `required: upper, lower`. See [Requiring that a password contain certain characters](#requiring-that-a-password-contain-certain-characters).*\r\n\r\nIf you do not specify the `max-consecutive` property then it defaults to being unbounded. That is, the user agent can generate a password with one or more arbitrary length runs of the same character (e.g. ooops).\r\n\r\nIf you specify the `required` property and do not specify the `allowed` property then the user agent will infer the value of the `allowed` property according to the rules in [How a user agent determines the `allowed` characters](#how-a-user-agent-determines-the-allowed-characters).\r\n\r\nFor example, to require a password have at least 8 characters consisting of a mix of uppercase and lowercase letters, at least one number, and at most two consecutive characters, add this to your markup:\r\n```\r\n<input type=\"password\" minlength=\"8\" passwordrules=\"required: upper; required: lower; required: digit; max-consecutive: 2\">\r\n```\r\n\r\nTo require at least one digit or one of -().&@?'#,/\"+ (not both), add this to your markup:\r\n```\r\n<input type=\"password\" minlength=\"8\" passwordrules=\"required: upper; required: lower; required: digit, [-().&@?'#,/&quot;+]; max-consecutive: 2\">\r\n```\r\n\r\nOr to require at least one of -().&@?'#,/\"+, add this to your markup:\r\n```\r\n<input type=\"password\" minlength=\"8\" passwordrules=\"required: upper; required: lower; required: digit; required: [-().&@?'#,/&quot;+]; max-consecutive: 2\">\r\n```\r\n\r\nAlternatively, to optionally allow one of -().&@?'#,/\"+, add this to your markup:\r\n```\r\n<input type=\"password\" minlength=\"8\" passwordrules=\"required: upper; required: lower; required: digit; allowed: [-().&@?'#,/&quot;+]; max-consecutive: 2\">\r\n````\r\n\r\nAnother example, to allow a password to contain an arbitrary mix of letters, numbers, and -().&@?'#,/\"+, add this to your markup:\r\n```\r\n<input type=\"password\" minlength=\"8\" passwordrules=\"allowed: upper, lower, digit, [-().&@?'#,/&quot;+]\">\r\n```\r\n\r\n**WARNING**: With the exception of the NOTE below, each property/value pair reduces the entropy of a user agent generated password and makes the password more likely to be guessed or brute-forced. The more characters that are required the more likely the user agent generated password can be guessed or brute-forced.\r\n\r\n**NOTE**: Setting the `passwordrules` attribute to `allowed: unicode` provides the most entropy for a user agent generated password. Omitting the `passwordrules` attribute or setting it to the empty string provides the second most entropy for a user agent generated password.\r\n\r\n### Custom character classes\r\n\r\nA custom character class is a list of ASCII characters that are surrounded by square brackets (e.g. [abc]). Any non-ASCII printable characters in the set are ignored. The dash character (-) is reserved as a special character. To list '-' as a literal character it must appear immediately after the opening square bracket '['. The right square bracket (]) is also reserved as a special character. To list ']' as a literal character it must appear immediately before the closing square bracket ']'.\r\n\r\n### Specifying the characters allowed to be in a password\r\n\r\nThe value of the `allowed` property is a comma-separated list of character class identifiers or [custom character classes](#custom-character-classes), or both. Each [custom characters class](#custom-character-classes) represents a set of characters that are allowed to be in the generated password. For example, if the `allowed` property is set to `[*]]` then the generated password is allowed to contain ']' and '*', but it is not allowed to contain '[' among other non-listed characters. If the `allowed` property is set to `digit, [@!]` then the generated password is allowed to contain one or more ASCII digits, one or more '@'s and one or more '!'s, but it is not allowed to contain '[' among other non-listed characters.\r\n\r\n### Requiring that a password contain certain characters\r\n\r\n~~You can require that a password contain certain characters or classes of characters by setting the value of the `required` property to a comma-separated list of character class identifiers or [custom character classes](#custom-character-classes), or both. For example, if the `required` property is set to `upper, digit` then the user agent [MUST](#how-a-user-agent-generates-a-password-based-on-passwordrules) generate a password that contains at least one ASCII uppercase letter and at least one digit. If `required` is set to `upper, [@!]` then the user agent [MUST](#how-a-user-agent-generates-a-password-based-on-passwordrules) generate a password that contains at least one ASCII uppercase letter and either '@' or '!'.~~\r\n*A user agent must generate a password that contains at least one character from each `required` property. For example, if the `passwordrules` attribute is set to `required: upper; required: digit` then the user agent [MUST](#how-a-user-agent-generates-a-password-based-on-passwordrules) generate a password that contains at least ASCII uppercase letter and at least one digit. If there is a single `required` property that is set to `upper, digit` then the user agent [MUST](#how-a-user-agent-generates-a-password-based-on-passwordrules) generate a password that contains at least one ASCII uppercase letter or at least one digit. If there is a single `required` property that is set to `upper, [@!]` then the user agent [MUST](#how-a-user-agent-generates-a-password-based-on-passwordrules) generate a password that contains at least one ASCII uppercase letter or '@' or '!'.*\r\n\r\n### Limiting the number of consecutive repeated characters\r\n\r\nThe value of `max-consecutive` is a non-negative integer that represents the maximum length of a run of consecutive identical characters that can be present in the generated password. For example, set `max-consecutive` to `2` to disallow a user agent from generating a password that contains a run of more than 2 of the same character (e.g. \"ooops\" - contains three consecutive o's).\r\n\r\n### How a user agent determines the `allowed` characters\r\n\r\nThe set of required characters MUST always be a subset of the set of allowed characters. If the value of `passwordrules` violates this constraint then the user agent MUST adjust the value of `allowed` to satisfy it. The following implications immediately fall out from this constraint:\r\n\r\n1. If you specify the `required` property and do not specify the `allowed` property then the `allowed` property is inferred to be the value of the `required` property.\r\n2. If you set both the `required` property and the `allowed` property then the user agent behaves as if the `allowed` property were set to the union of the value of the `allowed` property and the value of the `required` property. For example, if the `required` property is set to `lower` and the `allowed` property is set to `[abc0123]` then the user agent MUST behave as if the `allowed` property were set to `lower, [0123]`. Another example, if the `required` property is set to `lower` and the `allowed` property is set to `upper` then the user agent MUST behave as if the `allowed` property were set to `lower, upper`.\r\n3. If neither the `required` property nor the `allowed` property are specified then the user agent behaves as if the `allowed` property was set to `ascii-printable`.\r\n\r\n### How a user agent generates a password based on `passwordrules`\r\n\r\nA user agent will generate a password using an algorithm or heuristic of its choice that respects the following attributes of a password element (not necessarily in order): `minlength`, `maxlength`, and `passwordrules`. If the set of constraints imposed by the aforementioned attributes fail to meet the following minimum restrictions then they are considered nonconforming and the user agent is REQUIRED to ignore them:\r\n\r\n1. The maximum password length cannot be less than 12.\r\n2. Allowed characters must consist of at least two of the following character classes: ASCII uppercase letter, ASCII lowercase letters, digits.\r\n\r\nCharacters in the generated password MUST be expressed in [Normalization Form C](https://unicode.org/reports/tr15/#Norm_Forms) and must conform to the following [UAX31](https://unicode.org/reports/tr31/) profile:\r\n\r\n* Start := [ID_Continue + Pattern_Syntax + Pattern_White_Space](http://unicode.org/reports/tr31/#Table_Lexical_Classes_for_Identifiers), plus all characters from [Table 3](https://unicode.org/reports/tr31/#Table_Optional_Start), [Table 3a](https://unicode.org/reports/tr31/#Table_Optional_Medial), and [Table 3b](https://unicode.org/reports/tr31/#Table_Optional_Continue) except Join_Control characters (i.e. ZWJ, ZWNJ).\r\n* Continue := Start.\r\n* Medial := None.\r\n\r\n### Interaction with client-side form validation\r\n\r\nIt is not recommended to specify both the `pattern` attribute and the `passwordrules` attribute. \r\n\r\nThe `passwordrules` attributes participates in constraint validation. If the element's `value` attribute does not satisfy the criterion specified by the value of the `passwordrules` attribute then the element is in the \"suffering from a `passwordrules` mismatch\" validity state and the element is invalid for the purposes of constraint validation.\r\n\r\n### Confirmation password field\r\n\r\nSome web pages have both a password field (\"primary password field\") and a confirmation password field. The `passwordrules` attribute needs only to appear on one of these fields. If both fields have the `passwordrules` attribute then you must ensure that they have the same value. Otherwise, the user agent will behave as if both fields have set their `passwordrules` attribute to the result of the union of both field's `required` property (if any) and the intersection of both field's `allowed` property (if any) after simplifying the `passwordrules` attribute of both fields according to rules in [Using the `passwordrules` attribute](#using-the-passwordrules-attribute). For example, if a page contains the following markup:\r\n```html\r\n<input type=\"password\" name=\"password\" minlength=\"8\" passwordrules=\"required: upper, lower, digit, [-().&@?'#,/&quot;+]; max-consecutive: 2\">\r\n<input type=\"password\" name=\"confirmation-password\" minlength=\"8\" passwordrules=\"required: upper; allowed: [!]; max-consecutive: 3\">\r\n```\r\n\r\nThen the user agent must behave as if the markup was:\r\n```html\r\n<input type=\"password\" name=\"password\" minlength=\"8\" passwordrules=\"required: upper, lower, digit, [-().&@?'#,/&quot;+]; max-consecutive: 2\">\r\n<input type=\"password\" name=\"confirmation-password\" minlength=\"8\" passwordrules=\"required: upper, lower, digit, [-().&@?'#,/&quot;+]; max-consecutive: 2\">\r\n```"},"comment":{"url":"https://api.github.com/repos/whatwg/html/issues/comments/372540098","html_url":"https://github.com/whatwg/html/issues/3518#issuecomment-372540098","issue_url":"https://api.github.com/repos/whatwg/html/issues/3518","id":372540098,"user":{"login":"bsittler","id":63303,"avatar_url":"https://avatars2.githubusercontent.com/u/63303?v=4","gravatar_id":"","url":"https://api.github.com/users/bsittler","html_url":"https://github.com/bsittler","followers_url":"https://api.github.com/users/bsittler/followers","following_url":"https://api.github.com/users/bsittler/following{/other_user}","gists_url":"https://api.github.com/users/bsittler/gists{/gist_id}","starred_url":"https://api.github.com/users/bsittler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bsittler/subscriptions","organizations_url":"https://api.github.com/users/bsittler/orgs","repos_url":"https://api.github.com/users/bsittler/repos","events_url":"https://api.github.com/users/bsittler/events{/privacy}","received_events_url":"https://api.github.com/users/bsittler/received_events","type":"User","site_admin":false},"created_at":"2018-03-13T04:04:17Z","updated_at":"2018-03-13T04:04:17Z","author_association":"NONE","body":"@dbates-wk the updates are improvements from my point of view. A few issues still concern me:\r\n\r\n- So far as I can tell there is no limit on how many narrow-character-class `required:` limitations a site can impose, which means:\r\n   - unacceptable entropy-reduction is possible; I believe target minimum entropy levels for generators should be clearly stated in the proposal, even if no formula is given to compute the level based on the `passwordrules`\r\n   - in these cases selecting conforming password candidates from a less-restricted candidate list may take too long to terminate - e.g. a list generated naively based on random selection (for each character) from the printable-ASCII subset of `allowed:`; to overcome this I think the proposal needs to include at least a rough outline or pseudocode for a conforming generator with guaranteed termination\r\n- The character class syntax differs from JS regular expressions; is this intentional? If so, it should be noted more prominently; if not, the gaps should be closed\r\n - As an example: how would a requirement for one of `[`, `-` or `]` be expressed? I believe in JS regular expressions it would be `[-[\\]]`\r\n"}}
{"actor":{"display_login":"bsittler"}}