wicg / origin-policy Goto Github PK
View Code? Open in Web Editor NEW[On hold for now] A mechanism for origins to set their origin-wide configuration in a central location
License: Other
[On hold for now] A mechanism for origins to set their origin-wide configuration in a central location
License: Other
Since it is clear that we are talking about headers to be included I propose to restructure the JSON to group by "baseline", "fallback","cors-preflight". This eliminates the need for the the "type" attribute.
“baseline”: {
<baseline headers here>
},
“fallback”: {
<fallback headers here>
},
“cors-preflight”: {
<fancy CORS stuff here>
}
We ran into an issue in our implementation, where Origin Policy unnecessarily inflates an otherwise minor bug in header processing:
When (a faulty server | faulty proxy | faulty client) erroneously copies request headers into the response, and this also affects the Origin Policy announcement header (sec-origin-policy: 1), then this has the unfortunate effect of locking down the entire site. Furthermore, since the site operator is presumably not aware of the issue, they likely haven't prepared for sending the right header to delete the policy.
Reference: https://crbug.com/901477
As a work-around, we have chosen to advertise OP capability using the sentinel value for deleting a policy. (sec-origin-policy: 0)
Alternatives would be:
It would be nice to come up with a recommended mechanism for pinning policies that include nonces. On the one hand, this can be verbosely dealt with via a combination of baseline
and fallback
policies in the current syntax:
{
...
"csp": [
{
"policy": "script-src 'none'",
"type": "fallback"
},
{
"policy": "object-src 'none'",
"type": "baseline"
}
],
...
}
The latter would be applied to every request, the former only to those that don't set their own policy. So, a page that delivered Content-Security-Policy: script-src 'nonce-yay' 'strict-dynamic'
would end up with a policy of script-src 'nonce-yay' 'strict-dynamic', object-src 'none'
, which would merge into reasonable behavior.
Actually, maybe that's not so bad, now that I spell it out... I'm not sure a template system merging in additional response headers is any better, and it might be significantly worse/more complex.
First of all,
Security-Policy: "v1"
- Having an arbitrary version number feels funny, as it seems like it leaves room for error (updating the policy but forgetting to bump the version). Why not have the version be a hash of the json policy file? This would allow for trivial code to set the "version number" in headers (i.e. self updating) and would allow a nice belt and suspenders check on the client (you don't process a manifest unless it actually hashes to the same value provided in the header response).fallback-csp
(more broadly, fallbacks as a general feature), as we have run into this at GitHub. An early failure in normal request processing resulted in no CSP header getting set in the response. While we fixed the underlying issue, we also added a "fallback csp" on all our static error pages by setting a super strict policy via a meta
tag. That said, we would generally be fine if our fallback matched our regular policy. So, I wonder how often people will actually strongly prefer a different policy. It may be that it is generally not needed, so maybe the baseline-csp
would be sufficient. Or, maybe this could be made optional (and apply to other directives). Fore eample, there could be a fallback
attribute you can set for any (where it makes sense) of the top level keys in this config (ex. Setting fallback
for the referrer
directive probably makes sense).baseline-csp
policy, what effect does returning a Content-Security-Policy
header have? Taking GitHub as an example, we would like to have a base policy that applies to the vast majority of requests, but we would like to override certain directives on certain pages. For example, we add on an additional connect-src
to our policy on our payment pages (to allow connection to a third party payment processor). We don't want that source in our base policy, as it is not needed for 99% of requests. The most trivial solution would seem to be to prefer Content-Security-Policy
over the manifest to override things when needed. But, that isn't ideal, as we don't really want to have to deliver the entire policy via header given that part of the goal of the manifest is not having to send an ever growing policy via header responses. This issue may very well be unique to CSP, as a complete override via a header generally makes sense (since most headers are single purpose). But, I do wonder if CSP should evolve in coordination with this manifest to allow for more granular overrides. Using my payment example above, what we really want is some base policy, and then some way to do something like Content-Security-Policy: append-connect-src 'https://api.braintreegateway.com'
to append a single connect-src
to the base policy for this single response. Most people probably use a static policy, but once you are addicted to CSP cors
stuff feels a bit out of place. While I see the benefit of it, and CORS does have some security consequences, it doesn't feel like a "security policy" to me in quite the same way as the others. The other headers were explicitly added for security, where as the CORS header was just a "necessary evil" to make cross origin sharing work at all. I wonder if the Web App Manifest is a better home (though if these manifests meld into one then it doesn't really matter).I'll add more comments if/when I think of things. Thanks again!
/cc
Team CC - @oreoshake @mastahyeti @gregose @brentjo
Twitter CC - @ericlaw1979 @ScottHelme @marumari
Given an async update model (see the latest plans for version negotiation), where you have a list of allowed policies (which could include "none") plus a preferred policy, pages may want to know which policy actually got applied.
For example, consider a landing page with less-sensitive things, which allows the none policy. When the user goes to login, if the none policy was applied, then they'll do a normal browser navigation, so that when they enter the sensitive portion of the site, the preferred origin policy is applied. But if the preferred policy was applied, they'll do a nice Ajax navigation with some swooshy transitions.
I propose we add something like self.originPolicy
which allows the page to tell what got applied in this way.
Details to figure out:
originPolicy
, or originPolicyId
? The former is shorter; the latter is perhaps more accurate.self.originPolicy
, or self.originPolicy
in workers and document.originPolicy
in documents? It seems like origin policies will be applied per-Document, not per-Window, so splitting them makes more architectural sense. But that's more awkward for developers.https://w3c.github.io/webappsec-csp/cookies/ probably fits here better than it will in Feature Policy. Look into that, me.
/cc @ptoomey3
Let's avoid a new same-origin policy exception and follow the example Adam Barth set many years ago.
The newish version negotiation mechanism (introduced in #47) has a pretty fatal flaw. Consider the following scenario:
https://example.com/static-page.html
.
Cache-Control: max-age=86400
.Origin-Policy: allowed=("policy-1")
"policy-1"
to "policy-2"
, for some good reason.
static-page.html
) to send Origin-Policy: allowed=("policy-1" "policy-2"); preferred="policy-2"
, of course.https://example.com/dynamic-page.html
for the first time.
Cache-Control: no-store
.Origin-Policy: allowed=("policy-1" "policy-2"); preferred="policy-2"
header, so it uses "policy-1"
for the initial load, but updates the https://example.com/.well-known/origin-policy
cache entry to contain "policy-2"
in the background.https://example.com/dynamic-page.html
use "policy-2"
, as intended.https://example.com/static-page.html
.
Origin-Policy: allowed=("policy-1")
...https://example.com/.well-known/origin-policy
is "policy-2"
, which is not in the allowed list...https://example.com/static-page.html
---oh no.Notably, this problem did not happen with the previous design, because the previous design didn't restrict us to one origin policy per origin; instead it had multiple origin policies, at different URLs of the form Upon re-reading, the previous design handled this in a different (but also somewhat broken) way. Visiting the cached page would update the default origin policy for the origin back to the old policy. The impact of this was somewhat limited: it threw away the (at that time normative) in-memory cache, and made it so that pages without the https://example.com/.well-known/origin-policy/$policy-name
.Sec-Origin-Policy
header got the old policy.
This problem is also exacerbated by the change that allows any resource to deliver Origin-Policy
headers; although a long-lived HTML page is a bit rare these days, a long-lived image or JS bundle is common.
Having one origin policy per origin seems like an intuitively good thing. But, maybe it is not really something you can reconcile with the existence of a HTTP cache; as long as pages exist in the cache with a preference for an old version of the origin policy, it seems you need to keep that old version around.
I'll continue thinking about potential ways to fix this, but thoughts would be welcome...
Currently it does not. It could include the URL of the request for which the origin policy is being looked up.
Pro: I think it would make testing a lot easier? (See issue I'm about to open on the web platform tests repo.)
Con: the origin policy is supposed to be fairly "general", so sending a Referrer seems a bit weird?
I don't think HSTS gets cleared when you clear cookies or storage in browsers today. And I don't think it should given that it opens the user up to attacks.
If we're saying HSTS should be part of Origin Policy but we're also saying that Origin Policy has too much user tracking going on so needs to be cleared along with cookies, we're effectively making things less secure.
I'm not sure that's a good idea.
(And yes, configuring HSTS on a per-resource basis is not great, which is why we should just build further upon https://hstspreload.org/ and leave the header alone.)
@mnot's https://mnot.github.io/I-D/site-wide-headers/ points to a potentially better mechanism for the kinds of things that already have headers. Perhaps we should refactor things to:
{
...
"headers": {
"baseline": [
{
"name": "Content-Security-Policy",
"value": "object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests"
},
{
"name": "Strict-Transport-Security",
"value": "max-age=10886400; includeSubDomains; preload"
},
...
],
"fallback": [
{
"name": "Content-Security-Policy",
"value": "script-src 'none'"
},
]
}
...
}
That significantly simplifies the definition, improves upon Mark's concept with the fallback/baseline distinction, and leaves room for new origin-wide policies that aren't set via headers.
Would it work if the value in the Sec-Origin-Policy request header was an entropy limited hash (say 16 bits) of the Origin Policy content. The server could check it against the current OP to decide whether to initiate a Push, alleviating the privacy risk. If a new OP created a hash collision with a previous version, then an extra space could be recursively added to the content to avoid it.
Assuming that #14 is accepted, a (probably incomplete) list of candidates:
Strict-Transport-Security
Public-Key-Pins
Public-Key-Pins-Report-Only
Expect-CT
Content-Security-Policy
(not always site-wide)Server
P3P
Access-Control-Allow-Origin
(not always site-wide)Alt-Svc
(???)/cc @annevk
Like Access-Control-Allow-Headers, the headers item should have power to list Authorization header in addition to "*"
. CORSOptionList is currently specified to be "*"
or a list, and therefore it cannot. The algorithm at 3.4.4. doesn't consider "*"
in a list, and as a result it's giving more power to "*" than one in the Fetch Standard.
We can also choose to intentionally relax the requirement to list Authorization explicitly for Origin-Wide Policy, but needs to be discussed.
Example:
http://redirect.com/first
responses with a redirect to http://redirect.com/second
which redirects again to http://a.com
.
redirect.com might want to configure itself through a Origin Policy that affects the second and third redirect request, for example setting HSTS. I am not sure how referrers are handled for redirects from redirect.com
to a.com
but a Referrer Policy might also be interesting.
Question: Should we fetch the Origin Policy manifest on redirects?
Consistently naming it "cors-preflight" seems good. This should only affect requests, not responses.
Allowing credentials while not listing origins should not happen in valid examples, only invalid examples. (Or is Chrome security okay with allowing wildcarded access to credentialed content?)
The syntax should probably be such so that you can make separate declarations for requests without credentials (maybe there origins is *) and those with.
There should be a section on crossdomain.xml and how this is somewhat better since a) we still check on each request if the URL actually knows about the policy (although this doesn't help with cors-preflight, the justification for that can be that we require a specific list of origins if you want to allow credentials), and b) CORS is still required for responses.
It may often be the case that a server with a new policy available is nonetheless sufficiently satisfied with the version of the policy a client has to not mandate a synchronous update and the time-to-interact delays that would incur. Consider adding a token to instruct the UA to download the new policy asynchronously and continue using its cached policy for the current request. If no cached policy exists, download could be synchronous always.
The example says:
Origin-Policy: "policy-1"
Which is then somehow turned into /.well-known/origin-policy/v1
.
This might be an error, but I can't tell from the text in Section 2.3.1.
If an origin actually exists of many applications (suborigins), we probably need to offer some additional granularity around CORS and maybe CSP...
It isn't clear what the benefit of the Sec-Origin-Policy
request header is.
I get that it advertises support for the feature, but why should it broadcast the version it has?
You probably want to put the result of applying https://infra.spec.whatwg.org/#parse-json-from-bytes to the body into the store rather than an unparsed body.
Open question
Should we apply a manifest to sub-resources the same way as we do to navigation requests/responses?
Current state
An origin manifest is fetched on navigational requests, not for sub-resource loads. For the latter it means that when the page with origin a.com
loads a script from b.com
the manifest for b.com
is not fetched (consequently also not applied even if we have it already in cache).
Pro(s)
Let's assume b.com
from the initial example adds HSTS to the manifest file to no longer send HSTS along with every response. As it is the spirit of the mechanism, a sub-resource load no longer has origin wide effect but the manifest file makes configurations for the origin.
Con(s)
Similar to Upgrade-Insecure-Requests
we send along yet another request header with every single request which itself introduces quite some traffic in terms of extra bytes and we do not win much if at all.
Problem:
Imagine an manifest file with CSP defined but with one of the objects not having a "policy"
attribute like in
"content-security-policy": [{
"disposition": "enforce",
"allow-override": true
}],
Question:
How to handle CSP without a "policy"
attribute?
Discussion:
Eventually we apply whatever CSP defines. So we would be good. But it seems a bit silly to me to actually process it at all. IMO we have the following three options:
In case other attributes are missing, that is the disposition
or the allow-override
as defined in #19 (comment), I currently apply "enforce" and "false" as default values. Though this might be up for discussion as well, I find them far less "dramatic".
Problem
As outlined in the document, a baseline or fallback CSP would be a cool feature. To make this an actual usable feature we need to incorporate dynamic parts like nonces.
Proposal
A manifest allows to define CSPs as always except for nonces where Origin Policy templates CSP. It either expects no nonce value at all or simply replaces any given nonce on receiving a new one.
New nonce values are transmitted with the response that also confirms the version of the currently cached manifest. The response header value will be JSON fromatted.
Example
CSP in Manifest: script-src 'nonce-PRETTYRANDOM'
or simply script-src 'nonce'
The server response: Sec-Origin-Policy: { "version": "policy-1", "nonce": "NEWNONCE" }
"origin" perhaps?
https://github.com/WICG/origin-policy/blob/master/policy-format.md has "features"
as a single string, and "Content-Security-Policy"
as an array of strings.
For CSP it states
Note that - just as the headers - you can chain multiple policies by either listing them as seperate strings in the array of strings, or by merging them into one string and separating them by a semicolon.
I'm trying to understand whether we can converge these, or whether the divergence is intentional. Some questions:
H: 1\nH: 2
should be equivalent to H: 1,2
generally speaking.)From #monkey-patching-html
, it is not clear what happens if fetch fails to get the response in reasonable timeline and there are no cached policy. Do we block the rendering? Do we render anyway?
I can see how people would put a dedicated web server to serve manifests behind a load balancer, which opens attack vectors like DoS.
This [Sec-Origin-Policy] header MUST be ignored if Secure Contexts §is-url-trustworthy returns "Not Trustworthy" when executed upon the response’s URL.
Which basically means "Ignore Sec-Origin-Policy over HTTP". Do we need to do that? I think it's enough to just say "If the response is HTTPS we require HTTPS for manifest fetching". But in fact we respect that already anyway by re-using the response's origin to generate the OP manifest URL.
As we know HSTS and other critical headers are ignored when received over HTTP. Now let's assume http://a.com
uses the Origin Policy mechanism. The http:
leaves connections open for our man-in-the-middle attacker MitM.
The browser visits http://a.com/insecure
and with it the browser tries to download the manifest file M from http://a.com/.wellknown/M
. MitM can intercept and modify M to include for example HSTS or HPKP. Let's call the modified version M_mod. The headers are added to the response for http://a.com/insecure
but are ignored because HTTP.
The same browser now visits https://a.com/supersecure
. Though "M" (actually M_mod but the browser thinks it's M) is already in cache the protocol is different and therefore the origin. So it re-downloads M but now over https://
. Since now we use https:
MitM cannot tamper with it.
Regarding 1., with or without manifest file it is the same situation in terms of security, everything is open to MitM. No changes here. But allowing Origin Policy for HTTP will introduce all the advantages of Origin Policy (like you need to send less headers, you might skip CORS preflights, etc) to insecure connections.
If a response header (HSTS, CSP, Feature Policy) conflicts with the origin manifest, which one wins? Intuition says headers, but it's not discussed (or I couldn't find it). I would suspect the more specific scope would win, but I don't know if this is more generally defined elsewhere.
The sentence "Origin Policy Manifest files for a given origin MUST be located as suffixes to the well-known location /.well-known/origin-policy [RFC5785]." doesn't seem to define suffix.
The linked RFC only says: URI suffix: The name requested for the well-known URI, relative to "/.well-known/"; e.g., "example" (This also seems a bad definition to me, as "../foo" is a URI relative to "/.well-known/"). That's not a general definition of a suffix, just of the suffix member of a URL template, which is a URI "relative" to /.well-known/.
In particular, it's unclear which of the following, if any, are valid suffixes:
Edit: Some other ones:
Issue: revoking the manifest does not automatically revoke the effects of manifest included headers, e.g. HSTS, which can easily lead to confusion and misconfigurations.
Proposal:
allow to add the following to the object
“on-revoke”: { <chance to invalidate HSTS etc here> }
it allows to define what to invalidate when invalidating the manifest itself.
Regarding #66 I think it would be useful if allowed had special values besides null, in particular for resources you don't plan on updating and would not want to invalidate (if ever), but would like to use the latest policy for.
Problem:
Consider the following policy
{
"hsts": { ... },
"hsts": { ... }
}
JSON accepts this as valid JSON but when parsing only takes the last definition into account.
Question:
Do we rely on this JSON behaviour implicitly?
Discussion:
I personally would like to see this explicitly defined to be clear about the behaviour. This is important especially when it comes to configurations like for HSTS. For example for CSP we could easily merge multi-definitions as it was only one since based on #19 (comment) we will have a list as its value.
(The question was raised by Lucas Garron on https://groups.google.com/a/chromium.org/d/msg/blink-dev/mdkHs4jybG4/EBOVwTifAQAJ)
MegaCorp, Inc. wishes to ensure that an opt-in feature is enabled for each of the pages on https://example.com, while avoid the overhead associated with large response headers, and ensuring that the navigation request is subject to opt-in as well.
For example, example.com wants to enable Client-Hints for all requests on its origin. They can achieve this by specifying a policy that enables Client-Hints for supporting browsers:
{
"headers": [
{
"name": "Accept-CH",
"value": "DPR, Viewport-Width, Width",
"type": "baseline"
},
...
]
}
Once such a policy is active, the client should apply the opt-in policy to every request and, following the example above, enable Client-Hints advertisements on all outbound requests to example.com.
This same pattern can be used for any opt-in feature; it'll remove the need for browsers to develop custom "remember this opt-in" policy mechanism.
WDYT?
p.s. more color here for how/why this would be valuable for Client Hints specifically.
Presumably it should be another top-level dictionary member. Draw inspiration from the spec at https://w3c.github.io/webappsec-csp/#report-violation .
Parsing failures or policy mismatches should presumably get reported here, which will require spec updates in those parts.
If the origin policy is to be fetched with credentials mode being "omit", it'll end up using a separate HTTP connection unless whatwg/fetch#341 is fixed in all implementations somehow.
And I do think we want credentials mode to be "omit", especially if we want to fetch these resources out-of-band. (One could imagine a user agent gathering these from useragentserverfarm.com and then sending the appropriate ones to the end user in some kind of compressed format.)
Arguably it could take the empty string as value currently.
Not sure if the src file just needs to be recompiled to html. The document hosted at https://wicg.github.io/origin-policy/ still has the typo.
Yesterday at BlinkOn folks brought up two potential uses for origin policy I hadn't heard before. I'd like to record them here and get folks' thoughts, if any.
Resurrecting the entry point regulation spec: apparently a big problem with that spec was where the manifest should exist. Origin policy seems like the exact right place for it.
I'm not sure why entry point regulation was abandoned exactly, so I'm not sure whether this is a good or bad idea, but it's certainly interesting.
Tweaking the processing model for CSP frame-ancestors: it's possible to DDOS a server by iframing it a lot. Currently you can prevent the browser from displaying the contents of the iframe using CSP frame-ancestors, but that only happens after the request has already been sent, the response has been rendered, and then the browser looks at the headers and says "oh, nevermind, we don't want to display that response". (IIUC.) If the browser knew, via origin policy, that a particular page was prohibited from being used in an iframe, then it could just refuse to issue the request entirely, which would save server operators the CPU time spent responding to the request.
This seems related to some of the other ongoing work around embedder policy and sec-fetch-metadata, which I haven't yet read up on in detail.
There are multiple potential errors that could occur with an origin policy:
"id": "none"
"content-security"
)Origin-Policy
header is unparseable according to the structured headers spec.Origin-Policy
header is parseable but mismatches the schema:
allowed
's value is not a list./.well-known/origin-policy
, which matches the allowed=()
value in the Origin-Policy
header.Probably there are more.
Which of these errors should cause a "hard failure", i.e. a network error for any responses to which the origin policy would apply, potentially resulting in a user-facing interstitial, vs. a "soft failure", i.e. just proceeding with the null origin policy applied to the response?
People have mostly advocated for soft-failure so far. (7) has to be a hard failure, as it's specifically designed as a mechanism for causing hard failure. I'm wondering if there are any other cases from the above list (or elsewhere) where hard failure is appropriate.
There's also a distinction between types of soft failures: ones that invalidate the origin policy, and ones which can be ignored. So e.g. (4.ii) seems like it would invalidate the origin policy, whereas (4.iii) seems like it should be ignored. Note that invalidating an origin policy can lead to hard failure (7) if a restrictive allow=()
list is in play.
But, let's first focus on hard vs. soft, and then nail down the types of soft. Are there any things in this list people think should be hard failures?
The spec doesn't say how new members are defined; can it be done by publishing a W3C spec, or is there a registry?
Setting up registries is cheap...
The new update and version negotiation design removed the HTTP request header, Sec-Origin-Policy
, as I thought it was not needed with that design. However, that may have been a mistake, as it removes request-time feature detection.
In particular, what is the deployment story for sites that want to support both browsers that implement origin policy, and browsers that do not implement origin policy? With the old design (even with the variant implemented in Chrome that always sent Sec-Origin-Policy: 0
), the flow was to indicate the origin policy with the response when the request contains Sec-Origin-Policy
. Otherwise, you would send the current complement of headers (i.e. CSP, Feature Policy, HSTS, etc.).
With the new design, there is no such signal, so I can only think of the following possibilities:
User-Agent
whether the UA supports origin policy, and send current headers if not.Neither of these is great.
The quick fix here is to put the Sec-Origin-Policy: 0
header back in. However I wanted to check with some folks before doing so.
In particular this reasoning seems to imply that adding any new HTTP response header that supersedes a previous one, requires pairing it with a feature-detection HTTP request header, and sending that for every request. Maybe adding such headers is rare enough, that HTTP hasn't run into it much in the past, and this is really a special case? @mnot, any thoughts?
The current proposal forces the name of the "preferred" policy to be listed twice:
Origin-Policy: allowed=(null "my-policy" "my-old-policy"), preferred="my-policy"
Could Origin-Policy
instead take an ordered List of all "allowed" policy names, and treat the first policy as the de-facto “preferred” policy?
Origin-Policy: "my-policy", "my-old-policy", null
Pros: Simpler, lighter.
Cons: Not as self-explanatory. Less extensible? (to future keys besides allowed
/preferred
)
Support objects equivalent to the Document-Policy and Require-Document-Policy headers, as per
https://github.com/w3c/webappsec-feature-policy/blob/master/document-policy-explainer.md
which splits out several features currently defined in Feature-Policy header.
Possibly under the "feature" object?
(raised in #22)
Is it possible to deploy an origin policy that turns all fetches (client & subresources) into network errors? Is it possible that this would also prevent updating the origin policy?
I don't have an exact case in mind, but it might involve the origin manifest containing an entry for "Sec-Origin-Policy". Or it might be as simple as a CSP rule that disallows everything.
If so, we might need a 24hr max max-age like we have with service worker, so if a broken origin policy is deployed, it doesn't lock users out of a site forever.
Please close whatwg/fetch#210.
Thinking more about some of the privacy issues I'm wondering if we should require HTTP/2 or later and have a fixed URL for the policy. That way we might be able to address some of the performance issues by fetching the policy in parallel with whatever is requested from that origin.
(If we assume that everyone eventually needs a policy we could even do away with the response header and use 4xx / 200 + application/json as signal, plus HTTP cache semantics for updates?)
I'd generally interpret "version" to be a monotonically increasing value, with newer/higher versions superseding earlier versions. While "version" can be used in other contexts, where versions don't necessarily replace each other, I think it's more confusion than necessary. Can we call them policies, policy sets, configurations, or something without the implication?
Another option would be to explicitly define version as its intended use, as oppose to just specifying how to get it and how to use it (Which are a far cry from a plain text definition).
The MIME type should be consistent with that of the specification (and GitHub repository) and vice versa.
Question:
How do we handle multiple Sec-Origin-Policy
headers in a response (or the same for Sec-Origin-Manifest
in future)?
Discussion:
Spontaneously I would take the first valid header. But this should be defined somewhere.
(This question was asked by Lucas Garron on https://groups.google.com/a/chromium.org/d/msg/blink-dev/mdkHs4jybG4/EBOVwTifAQAJ)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.