@@ -578,6 +578,88 @@ fn authz_function_called_in_object() {
578578 assert ! ( scan_result. contains_vulns( 1 ) )
579579}
580580
581+ // Tests that calls to /wiki/api/v2/app/properties are in TRIVIAL_API_PREFIXES and
582+ // are not flagged by the AuthZ scanner even without a prior authorize() call.
583+ #[ test]
584+ fn wiki_api_v2_app_properties_not_flagged_by_authz ( ) {
585+ let test_forge_project = MockForgeProject :: files_from_string (
586+ "// src/index.tsx
587+ import ForgeUI, { render, Fragment, Macro, Text } from '@forge/ui';
588+ import api, { route } from '@forge/api';
589+
590+ const App = async () => {
591+ const res = await api.asApp().requestConfluence(route`/wiki/api/v2/app/properties`);
592+ return (
593+ <Fragment>
594+ <Text>Hello world!</Text>
595+ </Fragment>
596+ );
597+ };
598+
599+ export const run = render(<Macro app={<App />} />);
600+
601+ // manifest.yml
602+ modules:
603+ macro:
604+ - key: basic-hello-world
605+ function: main
606+ title: basic
607+ handler: nothing
608+ description: Inserts Hello world!
609+ function:
610+ - key: main
611+ handler: index.run
612+ app:
613+ id: ari:cloud:ecosystem::app/07b89c0f-949a-4905-9de9-6c9521035986
614+ permissions:
615+ scopes: []" ,
616+ ) ;
617+
618+ let scan_result = scan_directory_test ( test_forge_project) ;
619+ assert ! ( scan_result. contains_vulns( 0 ) )
620+ }
621+
622+ // A non-allowlisted Confluence path without authorize() SHOULD be flagged,
623+ // confirming wiki_api_v2_app_properties_not_flagged_by_authzis is actually exercising the allowlist.
624+ #[ test]
625+ fn non_allowlisted_confluence_path_flagged_by_authz ( ) {
626+ let test_forge_project = MockForgeProject :: files_from_string (
627+ "// src/index.tsx
628+ import ForgeUI, { render, Fragment, Macro, Text } from '@forge/ui';
629+ import api, { route } from '@forge/api';
630+
631+ const App = async () => {
632+ const res = await api.asApp().requestConfluence(route`/wiki/api/v2/pages`);
633+ return (
634+ <Fragment>
635+ <Text>Hello world!</Text>
636+ </Fragment>
637+ );
638+ };
639+
640+ export const run = render(<Macro app={<App />} />);
641+
642+ // manifest.yml
643+ modules:
644+ macro:
645+ - key: basic-hello-world
646+ function: main
647+ title: basic
648+ handler: nothing
649+ description: Inserts Hello world!
650+ function:
651+ - key: main
652+ handler: index.run
653+ app:
654+ id: ari:cloud:ecosystem::app/07b89c0f-949a-4905-9de9-6c9521035986
655+ permissions:
656+ scopes: []" ,
657+ ) ;
658+
659+ let scan_result = scan_directory_test ( test_forge_project) ;
660+ assert ! ( scan_result. contains_vulns( 1 ) )
661+ }
662+
581663#[ test]
582664fn secret_vuln_fetch_header ( ) {
583665 let test_forge_project = MockForgeProject :: files_from_string (
0 commit comments