{"action":"created","issue":{"url":"https://api.github.com/repos/whatwg/fetch/issues/98","labels_url":"https://api.github.com/repos/whatwg/fetch/issues/98/labels{/name}","comments_url":"https://api.github.com/repos/whatwg/fetch/issues/98/comments","events_url":"https://api.github.com/repos/whatwg/fetch/issues/98/events","html_url":"https://github.com/whatwg/fetch/issues/98","id":98185320,"number":98,"title":"Request for support for certificate pinning","user":{"login":"f0zi","id":11842740,"avatar_url":"https://avatars.githubusercontent.com/u/11842740?v=3","gravatar_id":"","url":"https://api.github.com/users/f0zi","html_url":"https://github.com/f0zi","followers_url":"https://api.github.com/users/f0zi/followers","following_url":"https://api.github.com/users/f0zi/following{/other_user}","gists_url":"https://api.github.com/users/f0zi/gists{/gist_id}","starred_url":"https://api.github.com/users/f0zi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/f0zi/subscriptions","organizations_url":"https://api.github.com/users/f0zi/orgs","repos_url":"https://api.github.com/users/f0zi/repos","events_url":"https://api.github.com/users/f0zi/events{/privacy}","received_events_url":"https://api.github.com/users/f0zi/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/whatwg/fetch/labels/needsinfo","name":"needsinfo","color":"bfe5bf"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":7,"created_at":"2015-07-30T14:37:52Z","updated_at":"2015-08-06T19:55:39Z","closed_at":null,"body":"**I'd like to request support for certificate pinning.** \r\n\r\nNote that this is not the same as HSTS/HPKP although it seems to be related.\r\n\r\nI see two use cases that I believe are both useful:\r\n\r\nGlobal\r\n---\r\n\r\nThe first one is to have a global hash of valid domains to valid fingerprints. All HTTPS requests would look up the domain in the hash and match the cert (chain) to the valid fingerprints. Unexpected certificates would fail the request.\r\n\r\nA request could have a flag that indicates whether it wants to opt out of this or weather the request should fail or instead just continue with a flag set. I do think that it should fail by default because this would allow to add certificate pinning to an application without changing all the fetch calls.\r\n\r\nExample:\r\n\r\n    GlobalFetch.addCertFingerprintsSha256({\r\n        \"*.example.com\": [ \"E7:EF:F9:08:26:0B:B2:81:74:E8:C6:65:95:42:35:C0:B0:19:7E:79:8D:E4:3F:54:82:1F:B3:3E:AB:8B:1E:A2\" ],\r\n        \"*.google.com\": [ \"61:53:B1:8A:15:64:51:13:6A:78:37:DB:8D:0F:5A:73:B9:30:8E:80:5C:83:C8:CD:0F:66:9A:B3:DD:74:80:1F\" ]\r\n    )\r\n\r\n    // somewhere else\r\n    GlobalFetch.fetch(\"https://...\") ... // will fail for anything but example.com and google.com or if any of those use an unexpected cert\r\n\r\n    GlobalFetch.fetch( { url: \"https://...\", certpinning: \"off\" }) ... // will not fail due to cert pinning\r\n\r\nPer call\r\n---\r\n\r\nThe second case is a per-call option. An additional parameter in the option hash would give valid expected fingerprints for this request. If the server cert does not match one of the passed fingerprints the request would fail (or be flagged).\r\n\r\nExample:\r\n\r\n    GlobalFetch.fetch( { url: \"https://www.example.com/\", certs_sha1: [ \"EC:AD:27:F6:69:AE:C4:FA:95:2F:6E:58:4A:74:D5:9C:8D:8A:12:5F\" ] }) ...\r\n\r\nThis could be combined with the global list of fingerprints with the same flag as in the global case, so the possible cases would be:\r\n- no certs, cert pinning off: default, no cert pinning, all request succeed\r\n- have global certs, cert pinning on \"strict\" by default\r\n- \"strict\": all requests have to match a known cert and fail if they don't\r\n- \"flag\": requests that don't match a know cert will be flagged\r\n- \"off\": certificate pinning tuned off for this request\r\n- \"private\": ignore global list, only use certs in the options. Fails the request if it does not match. This is the default if a list of certs is passed to the fetch call.\r\n- \"private-flag\" or just \"flag\" with certs passed in the options: Just like \"private\" but only flags the request.\r\n- \"merge\": The cert must match one of the global _or_ one of the passed certs.\r\n- \"merge-flag\": Like \"merge\" but only flags the request\r\n\r\nSince HPKP only supports sha256 certificate fingerprints (for now) I think it should at least support that. Sha1 might be an option as well. Just like HSTS the parameters or functions should have different names according to the fingerprint types they accept.\r\n\r\nI'm not sure about the specific names for the functions and parameters, any comments or suggestions are welcome.\r\n\r\nAs an alternative to this I could also see the server cert chain including the public keys and/or its fingerprints be exposed in the response which would allow the client to do cert pinning by itself. This could potentially be more useful for other applications (than cert pinning) but would also make cert pinning more tedious."},"comment":{"url":"https://api.github.com/repos/whatwg/fetch/issues/comments/128486172","html_url":"https://github.com/whatwg/fetch/issues/98#issuecomment-128486172","issue_url":"https://api.github.com/repos/whatwg/fetch/issues/98","id":128486172,"user":{"login":"igrigorik","id":10652,"avatar_url":"https://avatars.githubusercontent.com/u/10652?v=3","gravatar_id":"","url":"https://api.github.com/users/igrigorik","html_url":"https://github.com/igrigorik","followers_url":"https://api.github.com/users/igrigorik/followers","following_url":"https://api.github.com/users/igrigorik/following{/other_user}","gists_url":"https://api.github.com/users/igrigorik/gists{/gist_id}","starred_url":"https://api.github.com/users/igrigorik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/igrigorik/subscriptions","organizations_url":"https://api.github.com/users/igrigorik/orgs","repos_url":"https://api.github.com/users/igrigorik/repos","events_url":"https://api.github.com/users/igrigorik/events{/privacy}","received_events_url":"https://api.github.com/users/igrigorik/received_events","type":"User","site_admin":false},"created_at":"2015-08-06T19:55:39Z","updated_at":"2015-08-06T19:55:39Z","body":"I don't think this is going to work from client-land.. With a JS API any first- or third-party script would be able to inject arbitrary pin rules for any origin - this is bad, as it's trivial to abuse. Only the origin itself should be able to assert rules about which certs should be pinned and for how long, which is why header based registration works."}}