Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: introduce security related linter and fix warnings #106

Merged
merged 6 commits into from
Jul 9, 2020

Conversation

magicmatatjahu
Copy link
Member

Description

  • Add eslint-plugin-security package and configure it in project,
  • Bump eslint package to 7.X.X,
  • Introduce getMapKey util function for retrieve data by key from object - use it in models,
  • Fix warnings returned by eslint-plugin-security.

Related issue(s)
Resolves #103

@magicmatatjahu magicmatatjahu added the enhancement New feature or request label Jul 6, 2020
Copy link
Member

@derberg derberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome stuff mate, just a few questions to understand some decisions

lib/models/operation.js Show resolved Hide resolved
@@ -240,6 +230,7 @@ class Schema extends Base {
* @returns {Object<string, Schema|string[]>}
*/
dependencies() {
/* eslint-disable security/detect-object-injection */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why disable, we we cannot just use Map here. Which part linter doesn't like?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linter doesn't like the key variable. If you use Object.keys() then you have 100% sure, than variable is string and we don't do things like _json.dependencies[key](), so we avoid eval malicious code, so I decided to disable plugin in those lines. I could use utils helper createMapOfType, but as you can see, in one case we create Schema Type, in another we write raw value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like to disable rules unless it is a test or there is really nothing else we can do.
values are accessed by a key and with Map it is not the case so it is better, so I don't really get your explanation about _json.dependencies[key]()

lib/parser.js Outdated
@@ -154,6 +154,7 @@ async function customDocumentOperations(js, asyncapiYAMLorJSON, initialFormat, o

validateChannelParams(js, asyncapiYAMLorJSON, initialFormat);

/* eslint-disable security/detect-object-injection */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

js.channels can be converted into Map -> https://github.com/asyncapi/parser-js/pull/105/files#diff-c3d5db07c30dd8c16e1da041b6f90850R115

of course depends what part is a problem for the linter

Copy link
Member Author

@magicmatatjahu magicmatatjahu Jul 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is with retrieving value by channelName and opName variable. As you see, this variable will be in 100% strings.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And as I remember forEach method from ES6 Map cannot handle async functions, and in this function we must handle async conversion of Messages.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right about forEach but then you can just use for of

thing is that we should not assume that what we have now (100% string) will always be like that if the future, so better just to fix than ignore

lib/utils.js Outdated
};

utils.getMapKey = (obj, key) => {
return utils.getMapKeyOfType(obj, key);
};

utils.addExtensions = (obj) => {
obj.prototype.extensions = function () {
const result = {};
Object.keys(this._json).forEach(key => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as with others, we could make this._json a Map

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then users will have to get data via the get () method and not via the array index, and for me this is a breaking change. If we decided to use Map here, then we should also adjust whole methods, which return plain JS Object, to Map. Or probably I don't understand your suggestion :D

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you change it to a map only for forEach but in 193 still return pure json

lib/utils.js Outdated
@@ -157,31 +159,38 @@ utils.createMapOfType = (obj, Type) => {
if (!obj) return result;

Object.keys(obj).forEach(key => {
// eslint-disable-next-line security/detect-object-injection
result[key] = new Type(obj[key]);
});

return result;
};

utils.getMapKeyOfType = (obj, key, Type) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some naming issues here, now this function is basically not only for getting a typed map, so name is no longer getMapKeyOfType and hiding it with getMapKey seems strange too me 🤔
why not try renaming getMapKeyOfType to something more generic? with good jsdoc?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will try make it more generic :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also in 162 line, without eslint-disable, we should cast key to String like result[String(key)] = new Type(obj[String(key)]);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeap, do the casting

did you make changes here? I don't think so

Copy link
Member

@derberg derberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicmatatjahu added a few comments

@@ -240,6 +230,7 @@ class Schema extends Base {
* @returns {Object<string, Schema|string[]>}
*/
dependencies() {
/* eslint-disable security/detect-object-injection */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like to disable rules unless it is a test or there is really nothing else we can do.
values are accessed by a key and with Map it is not the case so it is better, so I don't really get your explanation about _json.dependencies[key]()

lib/parser.js Outdated
@@ -154,6 +154,7 @@ async function customDocumentOperations(js, asyncapiYAMLorJSON, initialFormat, o

validateChannelParams(js, asyncapiYAMLorJSON, initialFormat);

/* eslint-disable security/detect-object-injection */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right about forEach but then you can just use for of

thing is that we should not assume that what we have now (100% string) will always be like that if the future, so better just to fix than ignore

lib/utils.js Outdated
@@ -157,31 +159,38 @@ utils.createMapOfType = (obj, Type) => {
if (!obj) return result;

Object.keys(obj).forEach(key => {
// eslint-disable-next-line security/detect-object-injection
result[key] = new Type(obj[key]);
});

return result;
};

utils.getMapKeyOfType = (obj, key, Type) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeap, do the casting

did you make changes here? I don't think so

lib/utils.js Outdated
};

utils.getMapKey = (obj, key) => {
return utils.getMapKeyOfType(obj, key);
};

utils.addExtensions = (obj) => {
obj.prototype.extensions = function () {
const result = {};
Object.keys(this._json).forEach(key => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you change it to a map only for forEach but in 193 still return pure json

derberg
derberg previously approved these changes Jul 9, 2020
Copy link
Member

@derberg derberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WELL DONE 👏

@sonarqubecloud
Copy link

sonarqubecloud bot commented Jul 9, 2020

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@derberg derberg merged commit 9c5f891 into asyncapi:master Jul 9, 2020
@asyncapi-bot
Copy link
Contributor

🎉 This PR is included in version 0.25.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request released
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Introduce security related linter and fix existing problems
3 participants