From 864cd4b375b27473fc9ca8978e34f88ce319b501 Mon Sep 17 00:00:00 2001 From: Khemraj Rathore Date: Tue, 19 Dec 2023 13:30:37 +0530 Subject: [PATCH 1/2] fix - cookie name for block node --- .../tagger/sink/RegularSinkTagger.scala | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/scala/ai/privado/languageEngine/javascript/tagger/sink/RegularSinkTagger.scala b/src/main/scala/ai/privado/languageEngine/javascript/tagger/sink/RegularSinkTagger.scala index 34c9d4145..fb7c99b27 100644 --- a/src/main/scala/ai/privado/languageEngine/javascript/tagger/sink/RegularSinkTagger.scala +++ b/src/main/scala/ai/privado/languageEngine/javascript/tagger/sink/RegularSinkTagger.scala @@ -27,7 +27,7 @@ import ai.privado.cache.{DatabaseDetailsCache, RuleCache} import ai.privado.model.{Constants, DatabaseDetails, NodeType, RuleInfo} import ai.privado.tagger.PrivadoParallelCpgPass import ai.privado.utility.Utilities.addRuleTags -import io.shiftleft.codepropertygraph.generated.nodes.{Call, Identifier, Literal} +import io.shiftleft.codepropertygraph.generated.nodes.{Block, Call, Identifier, Literal} import io.shiftleft.codepropertygraph.generated.{Cpg, Operators} import io.shiftleft.semanticcpg.language.* @@ -62,6 +62,24 @@ class RegularSinkTagger(cpg: Cpg, ruleCache: RuleCache) extends PrivadoParallelC .code .headOption .getOrElse(node.code) + case node: Block => + /* + Handles case + serverSetCookieWithMaxAge({ /* <=== @libs/common/utils/cookie */ + ctx: context, + maxAge: ONE_YEAR_IN_SECONDS, + name: CookieName.LANG_PREFERENCE, + value: userPreferredLocale, + }); + */ + node.astChildren.isCall + .name(Operators.assignment) + .where(_.argument.argumentIndex(1).ast.code("name")) + .argument + .argumentIndex(2) + .code + .headOption + .getOrElse(node.code) case node => node.code }).stripPrefix("\"").stripSuffix("\"") val newRuleIdToUse = ruleInfo.id + "." + cookieName From 9d1359ac52cb2e9e73cf5cb8e06c09d8a8bb2628 Mon Sep 17 00:00:00 2001 From: Khemraj Rathore Date: Tue, 19 Dec 2023 14:14:57 +0530 Subject: [PATCH 2/2] added unit test case --- .../tagger/sink/RegularSinkTaggerTest.scala | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/test/scala/ai/privado/languageEngine/javascript/tagger/sink/RegularSinkTaggerTest.scala diff --git a/src/test/scala/ai/privado/languageEngine/javascript/tagger/sink/RegularSinkTaggerTest.scala b/src/test/scala/ai/privado/languageEngine/javascript/tagger/sink/RegularSinkTaggerTest.scala new file mode 100644 index 000000000..91e126042 --- /dev/null +++ b/src/test/scala/ai/privado/languageEngine/javascript/tagger/sink/RegularSinkTaggerTest.scala @@ -0,0 +1,72 @@ +package ai.privado.languageEngine.javascript.tagger.sink + +import ai.privado.cache.{RuleCache, TaggerCache} +import ai.privado.entrypoint.PrivadoInput +import ai.privado.languageEngine.javascript.tagger.sink.RegularSinkTagger +import ai.privado.model.* +import better.files.File +import io.joern.jssrc2cpg.{Config, JsSrc2Cpg} +import io.shiftleft.codepropertygraph.generated.Cpg +import io.shiftleft.semanticcpg.language.* +import org.scalatest.BeforeAndAfterAll +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec + +class RegularSinkTaggerTest extends AnyWordSpec with Matchers with BeforeAndAfterAll { + + "Cookie name" should { + "be tag properly for block node argument" in { + val cpg = code(""" + |const langPreferenceCookie = cookies[CookieName.LANG_PREFERENCE]; + |if (isUserSpanish(transformedBrowserLocale) || chromeFlag) { + | if (langPreferenceCookie) { + | userPreferredLocale = langPreferenceCookie; + | } else { + | setCookie({ /* <=== @libs/common/utils/cookie */ + | ctx: context, + | maxAge: ONE_YEAR_IN_SECONDS, + | name: CookieName.LANG_PREFERENCE, + | value: userPreferredLocale, + | }); + | } + |} + |""".stripMargin) + + cpg.tag.nameExact(Constants.id).value.headOption shouldBe Some( + Constants.cookieWriteRuleId + ".CookieName.LANG_PREFERENCE" + ) + } + } +} + +val sinkRule = List( + RuleInfo( + Constants.cookieWriteRuleId, + "Web Storage Cookie(Write)", + "", + Array(), + List("(?i)(.*setcookie.*)"), + false, + "", + Map(), + NodeType.REGULAR, + "", + CatLevelOne.SINKS, + catLevelTwo = Constants.storages, + Language.JAVASCRIPT, + Array() + ) +) +def code(code: String): Cpg = { + val inputDir = File.newTemporaryDirectory() + (inputDir / "sample.js").write(code) + val outputFile = File.newTemporaryFile() + val rule: ConfigAndRules = + ConfigAndRules(List(), sinkRule, List(), List(), List(), List(), List(), List(), List(), List()) + val ruleCache = new RuleCache() + ruleCache.setRule(rule) + val config = Config().withInputPath(inputDir.toString()).withOutputPath(outputFile.toString()) + val cpg = new JsSrc2Cpg().createCpgWithAllOverlays(config).get + new RegularSinkTagger(cpg, ruleCache).createAndApply() + cpg +}