From b837c56bec5a598bdd951e30e998e449f8f19305 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Mon, 22 Sep 2025 10:13:33 -0400 Subject: [PATCH] Refactor RootApi and GrapeApiClass constructors for improved readability; add getHelperSelf method to retrieve self parameter in helpers block. --- ruby/ql/lib/codeql/ruby/frameworks/Grape.qll | 39 +++++++++++--------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Grape.qll b/ruby/ql/lib/codeql/ruby/frameworks/Grape.qll index 4e178792572..95aa42fdfad 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Grape.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Grape.qll @@ -25,9 +25,7 @@ module Grape { * In other words, it does not subclass any other Grape API class in source code. */ class RootApi extends GrapeApiClass { - RootApi() { - not this = any(GrapeApiClass parent).getAnImmediateDescendent() - } + RootApi() { not this = any(GrapeApiClass parent).getAnImmediateDescendent() } } /** @@ -44,9 +42,7 @@ module Grape { * ``` */ class GrapeApiClass extends DataFlow::ClassNode { - GrapeApiClass() { - this = grapeApiBaseClass().getADescendentModule() - } + GrapeApiClass() { this = grapeApiBaseClass().getADescendentModule() } /** * Gets a `GrapeEndpoint` defined in this class. @@ -63,6 +59,20 @@ module Grape { // is invoked with an instance as the `self`. result = this.getModuleLevelSelf() } + + /** + * Gets the `self` parameter belonging to a method defined within a + * `helpers` block in this API class. + * + * These methods become available in endpoint contexts through Grape's DSL. + */ + DataFlow::SelfParameterNode getHelperSelf() { + exists(DataFlow::CallNode helpersCall | + helpersCall = this.getAModuleLevelCall("helpers") and + result.getSelfVariable().getDeclaringScope().getOuterScope+() = + helpersCall.getBlock().asExpr().getExpr() + ) + } } private DataFlow::ConstRef grapeApiBaseClass() { @@ -122,17 +132,12 @@ module Grape { */ private class GrapeParamsCall extends ParamsCallImpl { GrapeParamsCall() { - // Params calls within endpoint blocks - exists(GrapeApiClass api | - this.getMethodName() = "params" and - this.getParent+() = api.getADeclaration() - ) - or - // Params calls within helper methods (defined in helpers blocks) - exists(GrapeApiClass api, DataFlow::CallNode helpersCall | - helpersCall = api.getAModuleLevelCall("helpers") and - this.getMethodName() = "params" and - this.getParent+() = helpersCall.getBlock().asExpr().getExpr() + exists(API::Node n | this = n.getAMethodCall("params").asExpr().getExpr() | + // Params calls within endpoint blocks + n = grapeApiInstance() + or + // Params calls within helper methods (defined in helpers blocks) + n = any(GrapeApiClass c).getHelperSelf().track() ) } }