Skip to content

Javascript: Improve Restify support and add new Spife support #10663

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

Merged
merged 28 commits into from
Dec 15, 2022

Conversation

pwntester
Copy link
Contributor

@pwntester pwntester commented Oct 3, 2022

This PR improves Restify support and adds brand new support for Spife framework

@github-actions github-actions bot added the JS label Oct 3, 2022
Copy link
Contributor

@erik-krogh erik-krogh left a comment

Choose a reason for hiding this comment

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

two quick comments from a quick read of the code.

@pwntester pwntester changed the title Improve Restify support Javascript: Improve Restify support Oct 4, 2022
@pwntester pwntester changed the title Javascript: Improve Restify support Javascript: Improve Restify support and add new Spife support Oct 13, 2022
@pwntester pwntester marked this pull request as ready for review October 13, 2022 12:00
@pwntester pwntester requested a review from a team as a code owner October 13, 2022 12:00
@pwntester pwntester requested a review from erik-krogh October 13, 2022 12:01
@erik-krogh
Copy link
Contributor

The qldoc check is failing because you don't have a toplevel QLDoc in Spife.qll.

I think you should add a change-note to javascript/ql/lib/change-notes.

@pwntester pwntester force-pushed the restify_improvements branch from 2ebba03 to 573cad4 Compare October 13, 2022 13:09
Copy link
Contributor

@asgerf asgerf left a comment

Choose a reason for hiding this comment

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

Looks great, just a few things I noticed from a first read through. I haven't done a detailed review and I'm not very familiar with these libraries so will need more time to digest this.

@erik-krogh
Copy link
Contributor

You have a few failing tests:
javascript/ql/test/library-tests/frameworks/restify/tests.ql, javascript/ql/test/library-tests/frameworks/HTTP/RemoteRequestInput.ql, javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.ql.

Copy link
Contributor

@erik-krogh erik-krogh left a comment

Choose a reason for hiding this comment

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

A lot of minor comments after a readthrough.

My suggestions will definitely cause the autoformatter to fail, so you need to run that.

Comment on lines 364 to 356
reply.ref().(DataFlow::CallNode).getCalleeName() =
["reply", "cookie", "link", "header", "headers", "raw", "status", "toStream", "vary"] and
this = reply.ref().(DataFlow::CallNode).getArgument(0) and
rh = reply.getRouteHandler()
Copy link
Contributor

Choose a reason for hiding this comment

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

Calling reply.ref() two times gives you two different references, so you should only do that once here.

And I think you might have meant reply.ref().getAMethodCall(["reply", ...])? (Similar to what I pointed out in CookieDefinition).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, will fix it!

Comment on lines 396 to 391
TemplateObjectInput() {
reply.ref().(DataFlow::MethodCallNode).getMethodName() = "template" and
this = reply.ref().(DataFlow::MethodCallNode).getArgument(1)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't call reply.ref() twice, it gives two different references.

And I think this is right, I think you meant reply.ref().getAMethodCall("template"). (Similar to what I pointed out in CookieDefinition).

Copy link
Contributor

Choose a reason for hiding this comment

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

And there are also some other classes where you do eply.ref().(DataFlow::MethodCallNode).
Could you add tests for those so we are sure they are correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, thanks

Comment on lines 413 to 406
RedirectInvocation() {
this = reply.ref().(DataFlow::MethodCallNode) and
this.getMethodName() = "redirect"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above.

Comment on lines 428 to 431
exists(ReplySource reply |
reply.ref().(DataFlow::MethodCallNode).getMethodName() = "template" and
this = reply.ref()
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above.

Copy link
Contributor

Choose a reason for hiding this comment

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

I checked your test for this.

You have a call to reply.template(..) in your tests, and on that you test for templateInstantiation.
But your tests.ql don't have a case for templateInstantiation, so that is never tested.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice, catch, thanks, will add it!

@pwntester pwntester force-pushed the restify_improvements branch from 9d9efa6 to e080d8f Compare October 18, 2022 14:58
Comment on lines 364 to 356
reply.ref().(DataFlow::CallNode).getCalleeName() =
["reply", "cookie", "link", "header", "headers", "raw", "status", "toStream", "vary"] and
this = reply.ref().(DataFlow::CallNode).getArgument(0) and
rh = reply.getRouteHandler()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, will fix it!

Comment on lines 396 to 391
TemplateObjectInput() {
reply.ref().(DataFlow::MethodCallNode).getMethodName() = "template" and
this = reply.ref().(DataFlow::MethodCallNode).getArgument(1)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, thanks

Comment on lines 428 to 431
exists(ReplySource reply |
reply.ref().(DataFlow::MethodCallNode).getMethodName() = "template" and
this = reply.ref()
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice, catch, thanks, will add it!

Alvaro Muñoz and others added 2 commits October 18, 2022 21:41
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
@pwntester pwntester force-pushed the restify_improvements branch from e080d8f to b79f7f3 Compare October 18, 2022 19:42
@erik-krogh
Copy link
Contributor

The qldoc check is complaining about missing documentation on Restify::Restify::FormatterSetup::getAFormatterHandler.

@pwntester
Copy link
Contributor Author

@pwntester did you see my above suggestions?

Sorry I missed the notifications about the review comments. Will take a look ASAP

Alvaro Muñoz and others added 3 commits December 7, 2022 10:29
@pwntester
Copy link
Contributor Author

Thanks @erik-krogh I applied all suggestions, but had to revert 3 of them since there raised some ambiguity errors between parent types

Copy link
Contributor

@erik-krogh erik-krogh left a comment

Choose a reason for hiding this comment

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

Another round of comments.

Could you also do a merge with main? your base-commit is getting old.

)
}

API::Node getHandlerByName(string name) { result = this.getParameter(0).getMember(name) }
Copy link
Contributor

Choose a reason for hiding this comment

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

You also have to remove the rest of the uses of API::Node in this class.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@erik-krogh how would you rewrite this predicate? I thought about this result = this.getACallee().getParameter(0).(DataFlow::ObjectLiteralNode).getAPropertyRead(name) but ObjectLiteralNode is not compatible with Parameter

Copy link
Contributor

Choose a reason for hiding this comment

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

Just remove .(DataFlow::ObjectLiteralNode) from your attempt and you should be good.
getAPropertyRead() is defined on SourceNode, and both ObjectLiteralNode and ParameterNode are SourceNodes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I was not getting that option from the autocomplete menu, but I was missing a wrapping call to DataFlow::parameterNode()

Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
Copy link
Contributor

@erik-krogh erik-krogh left a comment

Choose a reason for hiding this comment

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

One more comment, and then I think we're there.

I have done an evaluation, and that looks fine.

Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
@erik-krogh
Copy link
Contributor

You fixed the implementation in 4ba3190, but you didn't add any tests to match.
I don't think you have any tests of Spife::RouteSetup (and the classes that depend on Spife::RouteSetup).

Those tests can probably be added as inline test comments in javascript/ql/test/library-tests/frameworks/Spife/lib/routes/index.js, and that file should probably also be expanded.

@pwntester
Copy link
Contributor Author

Thought about adding some tests as you proposed but I thought it was already tested indirectly and we have plenty of tests for handlers and those can only be correctly identified if the RouteSetup was matched correctly. Will add some explicit tests though

Comment on lines 9 to 10
import semmle.javascript.heuristics.AdditionalRouteHandlers

Copy link
Contributor

@erik-krogh erik-krogh Dec 14, 2022

Choose a reason for hiding this comment

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

Suggested change
import semmle.javascript.heuristics.AdditionalRouteHandlers

This was the reason that your tests "worked" before the fix.

Your Spife::RouteSetup and Spife::StandardRouteHandler were effectively unused in your tests before the fix, because your tests don't distinguish between heuristic and non-heuristic route-handlers.
You have to distinguish between heuristic and non-heuristic, otherwise you're only testing the former.

You can try to delete Spife::StandardRouteHandler, your tests still pass as they are right now.

You have a bunch of test failures when you delete this line, and I see three possible solution to that:

  • Accept the new test output (including failures), to document that some things can only be detected using the heuristic route-handlers.
  • Delete the tests lines are only detected by the heuristic route-handlers.
    This is fine, our other heuristic route-handlers don't really have tests.
  • Add another test that tests the heuristic route-handlers.

(The above assumes that no other bug surfaces from this).

Sorry for figuring this out so late, but I didn't look that closely at your test implementations (or your tests).

Comment on lines 9 to 10
import semmle.javascript.heuristics.AdditionalRouteHandlers

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
import semmle.javascript.heuristics.AdditionalRouteHandlers

Same here.

Copy link
Contributor

@erik-krogh erik-krogh left a comment

Choose a reason for hiding this comment

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

Lets get this merged.

I got a final confirmation evaluation running, but I'll do something if that doesn't turn out OK.

@erik-krogh erik-krogh merged commit 1500fa5 into github:main Dec 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants