w3c / webappsec-permissions-policy Goto Github PK
View Code? Open in Web Editor NEWA mechanism to selectively enable and disable browser features and APIs
Home Page: https://w3c.github.io/webappsec-permissions-policy/
License: Other
A mechanism to selectively enable and disable browser features and APIs
Home Page: https://w3c.github.io/webappsec-permissions-policy/
License: Other
We should investigate adding the following features to feature policy:
Geolocation (geolocation)
Midi (midi)
Encrypted media extensions (eme)
Microphone and Camera (microphone, camera, speakers)
All of these features currently have failure modes that can occur as the result of the user agent denying permission. The same failure mode can be used if the feature is disabled via feature policy.
We should also investigate changing the default value for these features to be "self" so that they are disabled by default in iframes to protect users from malicious iframes.
In §3.2.1 (cookie) there's an invalid example:
Given the following header:
Feature-Policy: {"disable":["cookie"]}
The following JavaScript code will throw a SecurityError exception:document.cookie = "a=b;Secure;SameSite"; alert(document.cookie);
https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1 says:
If "cookie-av"'s "attribute-value" is not a case-sensitive match for "Strict" or "Lax", ignore the "cookie-av".
SameSite
is missing an attribute value (Lax
or Strict
) and therefore will the cookie not be sat (in browsers with support for SameSite that is).
My suggestion is that we should have SameSite in cookie examples but we should add an attribute value, such as Lax
.
Imagine that a site wants to run relatively loosely-audited code on origin.com
, but restrict code that uses permissions to audited.origin.com
. The idea is that if origin.com
gets XSS'ed, none of the site's permissions can be mis-used by the attacker. With the current Feature Policy and Permission Delegation proposals, the site writes this like:
https://origin.com/index.html:
Feature-Policy: {"disable":["geolocation", "midi", "notifications", "push", "webrtc"], "target":"self"}
<iframe src="https://audited.origin.com/location_helper.html" permissions="geolocation"></iframe>
And audited.origin.com/location_helper.html
would be careful to validate requests from its embedder to be "safe" in some way.
However, if origin.com
gets XSS'ed, this doesn't help. The attacker can add a new <iframe src="https://evil.com/attack.html" permissions="geolocation"></iframe>
element to the page, and get full access without a prompt.
I think we need a whitelist of enabled origins in the Feature Policy line, if we want it to help protect against XSSes.
200 OK
Content-Type: text/html
Feature-Policy: {"disable":["sync-script"]}
...
<script src=/oops.js>
<script src=/app.js async>
GET /app.js
Feature-Policy: {"disable":["sync-script"]}
Beginnings of this logic in https://igrigorik.github.io/feature-policy/#set-request-policy
I think there is opportunity to use this feature to enforce best practices in web development and disable deprecated/inefficient/superseded features. This could help create a sort of "strict mode for HTML", whereby developers can set a HTTP header to encourage sensible design patterns. The no-docwrite
is a good example of this. Here are some other ideas (from https://discourse.wicg.io/t/proposal-sandbox-policy/1414):
force-strict-mode
: treat all scripts as if they had "use strict"; at the top, eliminating "sloppy mode" from the whole documentno-sync-storage
to disable local/session storage (the old synchronous APIs superseded by IndexedDB) - the Chrome Web Store already implements thisno-prefixed-features
- disable all prefixes, forcing standards-compliant uses onlyno-nonstandard-features
- similar to no prefixes, but to turn off all features not actually in the spec, e.g. window.orientation (replaced by screen.orientation), node.innerText (only exists for compatibility reasons), etc.Decline the PushManager.subscribe
permission check:
As a developer I need access to document.cookie
on my origin, but I want to disable access for one or more embedded contexts (for whatever reason). Today this is not possible...
Should we allow such use cases?
partial interface HTMLIFrameElement {
[PutForwards=value] readonly attribute DOMTokenList disable;
};
Where disable is a list of disable policy values for the embedee...
From: https://noncombatant.github.io/permission-delegation-api/
We recommend that UAs only allow permissions to be granted to embedded applications via explicit delegation from the embedding application.
...
A permission, generally, is an affordance in the UA to allow, deny, throttle, or otherwise regulate access to a powerful feature that the user, through the UA, may grant to the web origin. Examples of powerful features include [geolocation-API] and the getUserMedia API from [webrtc].
...
An embedder can delegate permissions it holds to its embedee(s), thus allowing the embedee to use the powerful feature to which the permission grants access. Similarly, an embedder can undelegate (revoke) a permission from an embedee.
The recommendation is to make powerful features mediated by Permissions API (i.e. features that require user permission) disabled by default in nested context's, and require the parent context to explicitly delegate permission to each embedee to (a) enable access to said feature, and (b) pass along the permission held by the embedder to the embedee.
Functional requirement: some features are off by default in nested contexts and the parent context should have a mechanism to selectively enable access to such features.
The enable policy
allows a developer to turn on certain features for a Document
or Worker
. The policy may be set and communicated via the Feature-Policy
HTTP Header Field, or via a declarative API.
Example A: Site A wants to enable Geolocation for all embedees.
200 OK
Feature-Policy: {enable: ["geolocation"], mode: "cascade"}Example B: Site B wants to enable a "trials" feature for its origin.
200 OK
Feature-Policy: {enable: ["opaque-token"]}Example C: Site A wants to also enable notifications for particular embedee.
<iframe enable="notifications" src="foo.com"></iframe>
foo.com has access to geolocation (via Example A) and notifications.
iframe
elementpartial interface HTMLIFrameElement {
[PutForwards=value] readonly attribute DOMTokenList enable;
};
The enable
attribute, when specified, enables specified features for the embedee running in the iframe
. Its value must be an unordered set of unique space-separated tokens that are ASCII case-insensitive, and is processed by the "parse enable response policy from value" algorithm.
Note: this would be called from "process response policy" which processes Feature-Policy
header, and "process attribute policy".
Given a list of ASCII case-insensitive tokens, this algorithm returns a list of valid enable features... Rough sketch:
enable
attribute:
iframe
element's src
attribute value.enforce
.null
.<insert ref to Origin Trials token processing algorithm>
algorithm returns "Enabled" when executed upon item and the document's global object:
self
.enforce
.null
.There is a bunch more to work through here, but I think the above would, more or less, allow us to merge Permission Delegation and Origin Trials into a single "enable" mechanism?
From current draft:
The policy must be delivered via an HTTP response header field to be processed by the client; the client must ignore any policy set via meta element's http-equiv attribute.
The feature policy needs to be set before the response is processed and before any subresource requests are initiated. Once active the policy also needs to apply for the lifetime of the document and is not allowed to be modified at runtime. Due to these requirements, meta element cannot be used to set the policy.
Origin-Trials folks, on the other hand, support <meta>
mechanism and are worried that lack of such adds a barrier to adoption ("I can't emit a header, I host my thing on GitHub Pages, or some such").
Practically speaking, I guess we could support meta, but we'd have to put a bunch of caveats:
Others? Is this practical and/or reasonable to implement?
The current spec prevents setting a feature-policy based on the meta tag.
The feature policy needs to be set before the response is processed and before any subresource requests are initiated. Once active the policy also needs to apply for the lifetime of the document and is not allowed to be modified at runtime. Due to these requirements, meta element cannot be used to set the policy.
I think this is unfortunate. There are some feature policies that probably deserve to be used in every new web app by default. For example I think there is a good argument that docwrite
, sync-script
and sync-xhr
should be disabled for all new projects; these features exist mainly for backwards compatibility and are best avoided. In issue 24 I also suggest further potentially universal policies like force-strict-mode
, no-sync-storage
and no-prefixed-features
.
While all professional web developers will have control over their HTTP headers, it's worth remembering the web has a broader audience than professionals. Beginners just starting out, developers working with third-party hosting servers, or even experienced developers just sharing a demo on something like a public Dropbox folder can not enforce any feature policy, because they don't know how or aren't allowed to change HTTP headers.
I think an even better argument is that it prevents templates from setting common-sense feature policies. Templates like the Twitter bootstrap, HTML5 boilerplate and others only provide the HTML files, but have no direct control over the HTTP headers. Also beginner's tutorials that want to recommend this as a kind of "use strict" mode for HTML have to delve in to HTTP configuration, instead of just saying "paste this at the top of every HTML file to turn off bad features". So while a common-sense universal feature policy might disable docwrite
, sync-script
, sync-xhr
and possibly others, this cannot easily propagate through templates or guides. This means more developers end up working with these features enabled (possibly accidentally), reducing the effectiveness of their web apps, and ultimately making it harder for browsers to remove these features.
There are technical reasons to disallow setting the meta tag or dynamically changing it, but I think it would still be acceptable to allow the tag but have some restrictions on it:
In other words, it has to be one of the first tags in the document (probably next after charset) but this still allows for the "paste-in good practices" uses outlined above.
WDYT?
In section "3.2.9 sync-xhr" it currently says:
"Disables synchronous XMLHttpRequest API: when open() method is called with async argument set to true, an InvalidAccessError except will be thrown."
Shouldn't this be "set to false" because this is blocking synchronous requests.
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open
What should we do in the case where an iframe navigates itself to an origin other than the one it is initialized to?
One case to consider here is, the embedder says enable="geolocation" for an iframe initialized to "good-site.com" but then the iframe is navigated to "bad-site.com". We don't want geolocation to be enabled.
A potential solution is to ignore enable attributes after a cross-origin navigation has occurred, unless the enable attribute is modified and then the iframe reloaded.
We also need to take care to apply the parent frames header policy correctly when an iframe is navigated to a new origin.
In the Introduction, the scope of a policy is left completely unclear. It's easy to read it and come to the conclusion that this stuff is about defining policies for the entire browser or browser session, akin to how a .pac file influences proxy policies.
It's clear from the later parts that this is not the intent; the policy is communicated on the response from which a Document object is initialized, and only affects objects within that Document's context (including, I assume, iframes within the Document).
This ought to be clear from the introduction.
It would be nice to be able to restrict content size of frames with the same API as it would require all of the same mechanisms. But it's not a feature and it requires an argument. So it's a bit of an awkward fit. How about a new "constraint" directive, like so:
Feature-Policy: {"constraint": {"max-content-size": 500000}, "target": ["https://example.com"]}
Other possible constraints include:
This seems to be intended, but it's not actually stated in the spec, that sub-resource requests should include the feature policy in its headers.
Disable the permission request by patching requestPermission(callback)
method:
Feature-Policy: {"enable": ["web-payments"], "target": ["https://bobpay.xyz"]}
By default PaymentRequest [1] interface should be hidden in embedded contexts, and "enable" should allow the site to expose said interface to the target origin. Conversely, the site should be able to "disable" the interface on self
.
[1] https://www.w3.org/TR/payment-request/#paymentrequest-interface
What is the purpose of being able to specify the target/origin the policy should apply to?
I mean, the Origin: header is supplied with each request, thus the web server could supply a dynamic Feature-Policy: that correspond to the server owner's wishes.
So for example, take this example:
SecureCorp Inc. is hosting an application on "https://example.com" and wants to disable WebRTC on its origin but enable it for a whitelisted embedee ("https://other.com"). It can do so by delivering the following HTTP response header to define a feature policy:
SecureCorp Inc. could simply have code like this (pseduocode, but you understand the idea):
if (Request.header('Origin').equals("other.com") && Request.IsSecure) {
Response.header("Feature-Policy") = '{"enable":["webrtc"]}';
}
else
{
Response.header("Feature-Policy") = '{"disable":["webrtc"]}';
}
I think dumping the "target" feature completely (and encourage web developers to implement it dynamically instead), would actually make the feature more secure, since the server then does not "leak" the security policy for origins unrelated to the request.
In particular for embedded contexts, it's not clear to me if features are enabled or disabled by default.
From the examples:
SecureCorp Inc. wants to disable use of Geolocation API within all browsing contexts whose origin is "https://example.com". It can do so by delivering the following HTTP response header to define a feature policy:
Feature-Policy: {"disable":["geolocation"], "target":["https://example.com"]}
The target is a list of one or more origins, which can include the applications origin and any third-party origin.SecureCorp Inc. is hosting an application on "https://example.com" and wants to disable WebRTC on its origin but enable it for a whitelisted embedee ("https://other.com"). It can do so by delivering the following HTTP response header to define a feature policy:
Feature-Policy: {"disable":["webrtc"], "target":["https://example.com"]},
{"enable":["webrtc"], "target":["https://other.com"]}
Some features are disabled by default in embedded contexts. The enable policy allows the application to selectively enable such features for whitelisted origins.
The first example implies that geolocation is enabled by default in frames. The second implies that it depends on the feature. Maybe this is covered elsewhere in the spec and I just didn't see it?
The current Examples focus on disabling features. Since many features are disabled by default on nested contexts, there should be a clear example of this. The one example of enabling is somewhat advanced.
The following text from that example seems out of place, as if it was an intro to such an example:
Some features are disabled by default in embedded contexts. The enable policy allows the application to selectively enable such features for whitelisted origins.
@noncombatant points out that it doesn't make sense to remember permission granted to sites like jsfiddle, since every path is controlled by a different person. It might make sense for Feature-Policy to let those sites declare this.
This is forking the discussion from #16 to focus on the OriginPolicy vs FeaturePolicy side of it.
My mental model on OriginPolicy is a bit different than what @mikewest and @igrigorik were discussing. I was picturing that we'd have FeaturePolicy and ContentSecurityPolicy. OriginPolicy would just be a way to enable either of those at an origin-wide level.
I think it would be really confusing for OriginPolicy to have it's own set of things it can control. How would we decide what makes sense for OriginPolicy vs the others.
Incidentally, the reason FeaturePolicy only allows toggles is because that makes for a simple platform for developers to understand and for browser vendors to implement. The benefits are defeated if we just add another kind of policy that can avoid that. If we were to do that, we may as well just loosen up FeaturePolicy.
ContentSecurityPolicy is a different beast. Where we can it should just control toggles on APIs, but when security is involved, that's not always an option. The benefit of security is such that we're more willing to take on some platform technical complexity. It's hard to make the argument for FeaturePolicy that the benefits are larger than the platform complexity of doing something more nuanced.
This came up as an idea while talking with @jyasskin...
Doing so would enable much more flexible enable/disable policies. For example:
Feature-Policy: {"disable":["geolocation"], "target":["cascade"]},
{"enable":["geolocation"], target:["https://foo.com"]}
Conceptually, above would disable Geolocation API for everyone except "https://foo.com": the disable policy is applied first and enable whitelists particular origins.
@mikewest curious to hear your thoughts.
There's nothing to be gained throwing there.
https://wicg.github.io/feature-policy/#feature-policy-http-header-field says:
When the user agent receives a Feature-Policy header field, it MUST process and enforce the serialized policy as described in 5.1 Integration with HTML.
Related to #44, including the current directive definition text, this section should acknowledge that clients may not recognize all features or directives members and thus may not process or enforce them as the server intends. In other words, while user agents should do the correct thing for their users, there is no mechanism for the server to guarantee that they are being applied. (In a compliant implementation, the feature policy advertised by each fetch could be used to check.)
"The meta element" section should have similar MUST language and acknowledgement.
It's fine for this effort to have a spec, but design shouldn't start there. It'd be better to outline the needs and proposed solutions in the form of a design doc & example code. E.g., see the Intersection Observer explainer: https://github.com/WICG/IntersectionObserver/blob/gh-pages/explainer.md
An idea/request from @jyasskin:
The implications of the default disable/enable policies defined in the Feature sections is unclear. They are set for all features and one can infer the meaning, but I did not see a reference to them in the algorithms or prose. Also, I believe the corresponding table headers should contain the word "Default".
I'd like to suggest Encrypted Media Extensions.
My main concern is security / attack surface. The 3rd party plug-ins have to be trusted with parsing and handling user supplied data.
Piece of mind will be asserting that the app, and any of its child scripts, won't be accessing this API at all.
A rough sketch of a ~v1 MVP based on recent discussions with various folks:
self
" as an additional keyword?It would be useful to also disable cookie storage via Set-Cookie headers as well as document.cookie writes, i.e. not just for iframes but for any resource.
Along the same lines it would also be useful to have disable feature directives for localStorage, indexDB etc.
Raised in whatwg/html#2122 (comment), it might be possible to put a noopener
policy into FP; rather than insisting that developers annotate every <a>
tag. Something like:
{"opener": ["self", "https://friendly-domain.com"]}
would make any links in the current page, except those to the whitelisted domains, behave as if the rel=noopener
attribute was added.
This may be an abuse of the whitelist; we've only used it for policy propagation, rather than selectively changing behaviour of parts of the current document, but it might be worth discussing.
(Possibly another interesting thing about making this part of FP is that we could apply it to windows created with window.open as well, which isn't possible with an attribute on <a>
.)
A top level document can have a policy that it sets which apply to itself and its children. It may have embedded documents (in iframes) that also have policies which they sets. These iframes may themselves embed documents which also have policies. We need to define how these things get composed/cascade down the frame tree.
Current proposal is to permanently disable the permissions request, similar to what we've done by restricting it to secure contexts.
Given the interventions of gating vibrate with user gesture, the semantics of using Feature Policy for vibrate might change, eg.,
/cc @ojanvafai @RByers @clelland @raymeskhoury @VicenteDiaz
See the two interventions below for context:
Title says it all. The following WebIDL redefines document.cookie
to be something else than it is now.
partial interface Document {
[Feature=cookie]
attribute USVString cookie;
};
I don't think that this is what you want to do (as it would wreck havoc), but I'm not sure either what it is you want to do.
Page author sets a policy that disables features [a, b, c]. How do we enforce said policy?
... any other strategies that are missing from the list above? Additional examples:
Given a mix of use cases that we're trying to prevent, ranging from disabling entire interfaces to rejecting calls based on certain method parameters... I don't think we can settle on a single strategy, but it would be nice to develop some ordered preference list.
This (feature policy) spec redefined permissions that are defined in the permissions api spec. Could this spec link to the permission api spec instead, so adding permissions (e.g. bluetooth, contacts, whatever we dream of next) doesn't require both specs to be updated?
The spec should normatively reference a definition of "origin" where appropriate, especially in the target member definition.
The reference should probably be https://html.spec.whatwg.org/multipage/browsers.html#concept-origin.
Implement a framework for exposing experimental features in the browser, but only to specific/registered origins, for limited duration and subject to global usage caps.
In effect, it's the opposite of the "Disable Policy". We should be able to share the same infrastructure, e.g..
Feature-Policy: {"trial":["token1", "token2"]}, {"disable":["webrtc","geolocation"]}
As far as FP is concerned, "trial policy" is a list of opaque tokens: we parse them out and we expose them, but we don't act on them... Other specs can hook in and run their own logic on said policy.
A "trial policy" has the following properties:
mode
is always set to enforce
target
is always set to self
report-to
is always set to null
Current proposal is to decline the permissions requests (requestMIDIAccess):
DOMException
with .name set to "SecurityError
".There is a number of different interfaces we need to consider here...
RTCPeerConnection()
constructor to check if disable webrtc policy is set, and throw a... SecurityError?... any others?
We should specify how IDN origins are handled, and what we do with unicode in the list of origins in in a policy string.
We could probably go one of two ways on this:
In the most recent updates to the explainer and spec, there are two ways to set a policy on a document:
Feature-Policy
HTTP headerallow*
attributes on <iframe>
elementsThe HTTP header is the only way for a document to declare its own policy (the iframe attributes are, of course, set by the embedding document), and is the only way to override the policy on the top-level document.
Since not every web page author has the ability to control the headers sent with their documents, it would be good to have a way to set the declared policy in HTML.
<meta http-equiv>
alternative to HTTP headers in HTMLWe can treat <meta>
elements as equivalent to HTTP headers, and allow document authors to include them in <head>
elements. This has the advantage of being consistent with the Origin Trials mechanism, as well as with other http-equiv
meta tags. We have to be careful in this case to not allow the tag to take effect after scripts have had a chance to run, though, as the policy enforced by the document should be effectively immutable, as far as scripts are concerned. Practically, I think this means we need to do one of two things:
Don't allow the policy to have any effect if it appears after <script>
or <link>
elements, or if inserted via script. This might cause problems in browsers that can run scripts (like Chrome extensions) that aren't included in the <head>
, since it may not be possible to include them early enough.
Require that the policy be delivered within the first 1024 bytes of the response, so that user agents can scan for it before starting to parse the document, like <meta charset>
. This isn't a scalable solution if other header-ish mechanisms want to adopt it as well; at some point, it's not going to be possible to cram everything into the first kilobyte.
<html>
tagThis means that there can be only one such declared policy (which may be a good thing), and forces it to be declared on the very first element in the document. If very large, it might push a <meta charset>
declaration out of the first kilobyte, but we might be able to define a shorthand format for such declarations. (If it doesn't look like it's trying to be an HTTP header, then maybe it doesn't need to have the same format)
I'm certainly open to other ideas here.
As a developer I want to enforce policy on my page and all subframes (i.e. "cascade" the policy), and I would also like to receive reports of any violations.
However... Forcing cross-origin embedee to report to the report-to endpoint defined by the embedder is probably a risky proposition - e.g. it could leak sensitive URL's that the embedee may not want to expose.
Q: Should we restrict reporting to same-origin violations only?
The Other and related mechanisms section says, "Feature Policy... provides an extensible mechanism," and the directive definition says, "Future versions of this document may define additional such members and user agents must ignore unknown members when parsing the object." However, there does not appear to be prose about adding new features or how implementations should handle unrecognized features, including those added by new versions of the spec.
It's probably worth addressing backwards compatibility considerations, adding Feature Policy checks to specs early, instructions for adding new features to this document, etc.
Such text may also want to recommend default policies for new features, which I believe would be [self
, null
] and null
.
webvr
should be included to the list of features. See immersive-web/webxr#86.
/cc @toji
From front page:
This document was published by the WICG as an Editor's Draft. If you wish to make comments regarding this document, please send them to @w3.org (subscribe, archives) with [feature-policy] at the start of your email's subject. All comments are welcome.
That won't work - I assume a specific mailing list was intended, but I don't know which.
We should decide how to handle unrecognized / unparsable input in policy strings.
I feel pretty strongly that we should be ignoring, for the sake of future compatibility, any unrecognized feature names. This way, any implementation can add new features that only they support, and other browsers can ignore them.
Similarly (though less strongly,) if we see an origin that we don't recognize, or doesn't even look like an origin, we should ignore that as well. Currently, we have two non-originy-origins, "self" and "*". I can imagine that in the future, there might be a need for a third one, or that some browsers may recognize as origins strings that other ones don't. In that case, it would be best to ignore them if we encounter them.
On the other hand, some errors might render a whole part of the feature policy string unusable. If we see something like this:
{"cookie": ["*"], "vibrate": [], "geolocation": {"here's something": "that isn't an array"}}
Should we ignore the geolocation
policy, but still enforce the cookie
and vibrate
policies? (I think so, but there might be reasons to just ignore the entire policy at that point)
We've been making steady progress on this end on Feature Policy and, as is usually the case, once you start implementing, you discover all kinds of opportunities to clarify and simplify things.
Latest explainer and a couple of highlights below:
https://docs.google.com/document/d/1k0Ua-ZWlM_PsFCFdLMa8kaVTo32PeNZ4G7FFHqpFx4E/edit
You'll notice that the explainer takes a slightly different (whitelist based) approach from the one we were exploring in earlier drafts of this proposal (note: the spec doc is out of date, ignore it for now and refer to the explainer instead). The end result is the same but—I think—much cleaner both conceptually and in terms of implementation.
Speaking of implementation, @clelland and @raymeskhoury have been busy building out a prototype in Chrome and are making great progress - we should have a working demo soon! For the first version we're targeting a small set of features that will be controlled via this mechanism: Vibrate API, getUserMedia, and maybe a few other related permissions based APIs. At a minimum, this would bring coherence into the growing mess of "allowX" iframe attribute proposals, which would already be a nice win for the platform! From there (v2+), we can then reuse the same mechanism to expose control over the long list of other features that folks have been asking for.
Would love to hear any thoughts and feedback!
Outstanding v1 issues: https://github.com/WICG/feature-policy/milestone/1
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.