{"action":"created","issue":{"url":"https://api.github.com/repos/kriskowal/q/issues/741","labels_url":"https://api.github.com/repos/kriskowal/q/issues/741/labels{/name}","comments_url":"https://api.github.com/repos/kriskowal/q/issues/741/comments","events_url":"https://api.github.com/repos/kriskowal/q/issues/741/events","html_url":"https://github.com/kriskowal/q/issues/741","id":114542563,"number":741,"title":"security issue: imposes one doman context over the other","user":{"login":"dimichgh","id":1390164,"avatar_url":"https://avatars.githubusercontent.com/u/1390164?v=3","gravatar_id":"","url":"https://api.github.com/users/dimichgh","html_url":"https://github.com/dimichgh","followers_url":"https://api.github.com/users/dimichgh/followers","following_url":"https://api.github.com/users/dimichgh/following{/other_user}","gists_url":"https://api.github.com/users/dimichgh/gists{/gist_id}","starred_url":"https://api.github.com/users/dimichgh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimichgh/subscriptions","organizations_url":"https://api.github.com/users/dimichgh/orgs","repos_url":"https://api.github.com/users/dimichgh/repos","events_url":"https://api.github.com/users/dimichgh/events{/privacy}","received_events_url":"https://api.github.com/users/dimichgh/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-11-02T07:40:04Z","updated_at":"2015-12-12T04:36:30Z","closed_at":null,"body":"The issue is observed when there is a common access to the data source, which is cached as a promise.\r\nThe domain from which resolve/reject is called imposes its context on all other promise.then/catch calls.\r\nThis was fixed in bluebird by using process.domain.bind().\r\n\r\n```javascript\r\n'use strict';\r\n\r\nvar Q = require('q');\r\nvar Assert = require('assert');\r\n\r\ndescribe.only(\"security issue when accessing common data via promise\", function () {\r\n    var Domain = require(\"domain\");\r\n\r\n    var cache;\r\n    function getCommonData(reject) {\r\n        if (cache) {\r\n            return cache;\r\n        }\r\n\r\n        var deferred = Q.defer();\r\n\r\n        setTimeout(function () {\r\n            if (reject) {\r\n                return deferred.reject(new Error(\"test error\"));\r\n            }\r\n            deferred.resolve(\"data\");\r\n        }, 100);\r\n\r\n        cache = deferred.promise;\r\n        return cache;\r\n    }\r\n\r\n    function setupContext(name, next) {\r\n        var domain = Domain.create();\r\n        domain.run(function () {\r\n            domain.testName = name;\r\n\r\n            next();\r\n        });\r\n    }\r\n\r\n    function validate(expected, done) {\r\n        try {\r\n            Assert.equal(expected, process.domain.testName);\r\n        }\r\n        catch (err) {\r\n            return done(err);\r\n        }\r\n        done();\r\n    }\r\n\r\n    function request(name, reject, done) {\r\n        setupContext(name, function () {\r\n            // now access common data\r\n            getCommonData(reject).then(function () {\r\n                // validate context\r\n                validate(name, done);\r\n            }, function (err) {\r\n                validate(name, done);\r\n            });\r\n        });\r\n    }\r\n\r\n    function countDone(count, done) {\r\n        return function _done(err) {\r\n            if (err) {\r\n                count = -1; // skip the rest\r\n                return done(err);\r\n            }\r\n            count--;\r\n            if (!count) {\r\n                done();\r\n            }\r\n        };\r\n    }\r\n\r\n    it(\"one domain should not impose its domain context onto the other domain context via common promise, resolve\", function (done) {\r\n        cache = undefined;\r\n        done = countDone(2, done);\r\n\r\n        setImmediate(request.bind(null, \"John\", false, done));\r\n        setImmediate(request.bind(null, \"Bob\", false, done));\r\n    });\r\n\r\n    it(\"one domain should not impose its domain context onto the other domain context via common promise, reject\", function (done) {\r\n        cache = undefined;\r\n        done = countDone(2, done);\r\n\r\n        setImmediate(request.bind(null, \"John\", true, done));\r\n        setImmediate(request.bind(null, \"Bob\", true, done));\r\n    });\r\n\r\n});\r\n\r\n```"},"comment":{"url":"https://api.github.com/repos/kriskowal/q/issues/comments/164109981","html_url":"https://github.com/kriskowal/q/issues/741#issuecomment-164109981","issue_url":"https://api.github.com/repos/kriskowal/q/issues/741","id":164109981,"user":{"login":"dimichgh","id":1390164,"avatar_url":"https://avatars.githubusercontent.com/u/1390164?v=3","gravatar_id":"","url":"https://api.github.com/users/dimichgh","html_url":"https://github.com/dimichgh","followers_url":"https://api.github.com/users/dimichgh/followers","following_url":"https://api.github.com/users/dimichgh/following{/other_user}","gists_url":"https://api.github.com/users/dimichgh/gists{/gist_id}","starred_url":"https://api.github.com/users/dimichgh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dimichgh/subscriptions","organizations_url":"https://api.github.com/users/dimichgh/orgs","repos_url":"https://api.github.com/users/dimichgh/repos","events_url":"https://api.github.com/users/dimichgh/events{/privacy}","received_events_url":"https://api.github.com/users/dimichgh/received_events","type":"User","site_admin":false},"created_at":"2015-12-12T04:36:30Z","updated_at":"2015-12-12T04:36:30Z","body":"it is really confusing how to add tests in PR for the module.\r\nHere's the possible fix:\r\nhttps://github.com/dimichgh/q/commit/e9d3fec5dcfd8503e68ad089b9a5e93f35692f16\r\nYou can integrate the above tests into the spec."}}