From 7e819277ddeda3c34c5f82c19746d05716f1e69f Mon Sep 17 00:00:00 2001 From: dxu2atlassian <136645827+dxu2atlassian@users.noreply.github.com> Date: Mon, 6 Jan 2025 23:42:59 -0800 Subject: [PATCH] Augment parsing logic after manual testing, test cases fix --- crates/forge_analyzer/src/definitions.rs | 27 ++++++++++--------- crates/fsrt/src/test.rs | 4 +-- .../issue-1-resolver-with-vuln/src/index.js | 2 +- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/crates/forge_analyzer/src/definitions.rs b/crates/forge_analyzer/src/definitions.rs index 07fe2f5e..e769fc05 100644 --- a/crates/forge_analyzer/src/definitions.rs +++ b/crates/forge_analyzer/src/definitions.rs @@ -993,13 +993,14 @@ impl FunctionAnalyzer<'_> { } fn resolve_jira_api_type(url: &str) -> Option { + // Pattern matching to classify, eg: api.[asApp | asUser]().requestJira(route`/rest/api/3/myself`); match url { url if url.starts_with("/rest/servicedeskapi/") => { Some(IntrinsicName::RequestJiraServiceManagement) } url if url.starts_with("/rest/agile/") => Some(IntrinsicName::RequestJiraSoftware), // Accept Jira API v2.0 or v3.0 - url if url.starts_with("/rest/api/3/") || url.starts_with("/rest/api/2/") => { + url if url.starts_with("/rest/api/2/") || url.starts_with("/rest/api/3/") => { Some(IntrinsicName::RequestJira) } _ => { @@ -1024,20 +1025,20 @@ impl FunctionAnalyzer<'_> { let function_name = if *last == "requestJira" { // Resolve Jira API requests to either JSM/JS/Jira as all are bundled within requestJira() match first_arg { - Expr::Tpl(template) => { - let url = template - .quasis - .iter() - .map(|quasi| quasi.raw.as_str()) - .collect::(); - - resolve_jira_api_type(&url).unwrap_or_else(|| { - warn!("Falling back to any Jira request"); - IntrinsicName::RequestJiraAny - }) + Expr::TaggedTpl(TaggedTpl { tpl, .. }) => { + if let Some(TplElement { raw, .. }) = tpl.quasis.first() { + let url = raw.clone(); + resolve_jira_api_type(&url).unwrap_or_else(|| { + // Conservatively assume any of Jira APIs may be used if we can't statically determine which one + warn!("Falling back to any Jira request"); + IntrinsicName::RequestJiraAny + }) + } else { + warn!("No url identifiable"); + return None; // TODO: handle the error, throw here? + } } _ => { - // Conservatively assume any of Jira APIs may be used if we can't statically determine which one warn!("First parameter to requestJira() is invalid"); IntrinsicName::RequestJiraAny } diff --git a/crates/fsrt/src/test.rs b/crates/fsrt/src/test.rs index 74f462ed..a39d8722 100644 --- a/crates/fsrt/src/test.rs +++ b/crates/fsrt/src/test.rs @@ -600,7 +600,7 @@ fn basic_authz_vuln() { function getText({ text }) { - api.asApp().requestJira(route`rest/api/3/issue`); + api.asApp().requestJira(route`/rest/api/3/issue`); return 'Hello, world!\n' + text; } @@ -786,7 +786,7 @@ fn rovo_function_basic_authz_vuln() { function getText({ text }) { - api.asApp().requestJira(route`rest/api/3/issue`); + api.asApp().requestJira(route`/rest/api/3/issue`); return 'Hello, world!\n' + text; } diff --git a/test-apps/issue-1-resolver-with-vuln/src/index.js b/test-apps/issue-1-resolver-with-vuln/src/index.js index aca7752e..28cd83bc 100644 --- a/test-apps/issue-1-resolver-with-vuln/src/index.js +++ b/test-apps/issue-1-resolver-with-vuln/src/index.js @@ -4,7 +4,7 @@ import api, { route } from '@forge/api'; // src/lib/get-text.ts function getText({ text }) { - api.asApp().requestJira(route`rest/api/3/issue`); + api.asApp().requestJira(route`/rest/api/3/issue`); return 'Hello, world!\n' + text; }