Skip to content

Commit 32f1b4f

Browse files
Augment parsing logic after manual testing, test cases fix
1 parent 8becec8 commit 32f1b4f

File tree

3 files changed

+17
-18
lines changed

3 files changed

+17
-18
lines changed

crates/forge_analyzer/src/definitions.rs

+14-15
Original file line numberDiff line numberDiff line change
@@ -993,17 +993,18 @@ impl FunctionAnalyzer<'_> {
993993
}
994994

995995
fn resolve_jira_api_type(url: &str) -> Option<IntrinsicName> {
996+
// Pattern matching to classify, eg: api.[asApp | asUser]().requestJira(route`/rest/api/3/myself`);
996997
match url {
997998
url if url.starts_with("/rest/servicedeskapi/") => {
998999
Some(IntrinsicName::RequestJiraServiceManagement)
9991000
}
10001001
url if url.starts_with("/rest/agile/") => Some(IntrinsicName::RequestJiraSoftware),
10011002
// Accept Jira API v2.0 or v3.0
1002-
url if url.starts_with("/rest/api/3/") || url.starts_with("/rest/api/2/") => {
1003+
url if url.starts_with("/rest/api/2/") || url.starts_with("/rest/api/3/") => {
10031004
Some(IntrinsicName::RequestJira)
10041005
}
10051006
_ => {
1006-
warn!("Invalid Jira API URL format: {}", url);
1007+
warn!("Provided Jira API URL: {:?} is neither Jira, JS, JSM!", url);
10071008
None
10081009
}
10091010
}
@@ -1024,21 +1025,19 @@ impl FunctionAnalyzer<'_> {
10241025
let function_name = if *last == "requestJira" {
10251026
// Resolve Jira API requests to either JSM/JS/Jira as all are bundled within requestJira()
10261027
match first_arg {
1027-
Expr::Tpl(template) => {
1028-
let url = template
1029-
.quasis
1030-
.iter()
1031-
.map(|quasi| quasi.raw.as_str())
1032-
.collect::<String>();
1033-
1034-
resolve_jira_api_type(&url).unwrap_or_else(|| {
1035-
warn!("Falling back to any Jira request");
1036-
IntrinsicName::RequestJiraAny
1037-
})
1028+
Expr::TaggedTpl(TaggedTpl { tpl, .. }) => {
1029+
if let Some(TplElement { raw, .. }) = tpl.quasis.first() {
1030+
resolve_jira_api_type(raw).unwrap_or_else(|| {
1031+
// Conservatively assume any of Jira APIs may be used if we can't statically determine which one
1032+
warn!("Falling back to any Jira request");
1033+
IntrinsicName::RequestJiraAny
1034+
})
1035+
} else {
1036+
panic!("No url identifiable to classify requestJira() type");
1037+
}
10381038
}
10391039
_ => {
1040-
// Conservatively assume any of Jira APIs may be used if we can't statically determine which one
1041-
warn!("First parameter to requestJira() is invalid");
1040+
warn!("Unable to classify requestJira() type");
10421041
IntrinsicName::RequestJiraAny
10431042
}
10441043
}

crates/fsrt/src/test.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ fn basic_authz_vuln() {
600600
601601
602602
function getText({ text }) {
603-
api.asApp().requestJira(route`rest/api/3/issue`);
603+
api.asApp().requestJira(route`/rest/api/3/issue`);
604604
return 'Hello, world!\n' + text;
605605
}
606606
@@ -786,7 +786,7 @@ fn rovo_function_basic_authz_vuln() {
786786
787787
788788
function getText({ text }) {
789-
api.asApp().requestJira(route`rest/api/3/issue`);
789+
api.asApp().requestJira(route`/rest/api/3/issue`);
790790
return 'Hello, world!\n' + text;
791791
}
792792

test-apps/issue-1-resolver-with-vuln/src/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import api, { route } from '@forge/api';
44

55
// src/lib/get-text.ts
66
function getText({ text }) {
7-
api.asApp().requestJira(route`rest/api/3/issue`);
7+
api.asApp().requestJira(route`/rest/api/3/issue`);
88
return 'Hello, world!\n' + text;
99
}
1010

0 commit comments

Comments
 (0)