Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate taintbench #1

Open
wants to merge 181 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
181 commits
Select commit Hold shift + click to select a range
ada29f5
comment print
Jclavo Dec 22, 2024
e6ad1c9
create AndroidTaintBenchSuiteTest
Jclavo Dec 22, 2024
6c7652a
use standar trait
Jclavo Dec 24, 2024
19de1b3
RoidSecSpec extends AndroidTaintBenchTest
Jclavo Dec 24, 2024
26f3bae
test RoidSecSpec
Jclavo Dec 24, 2024
cf8d402
move to folder specs
Jclavo Dec 24, 2024
0cb1ac9
remove comment
Jclavo Dec 24, 2024
2b69db2
ExampleSpec
Jclavo Dec 24, 2024
449850d
sourceList
Jclavo Dec 24, 2024
aac650c
sinkList
Jclavo Dec 24, 2024
4024cd2
backflash
Jclavo Dec 24, 2024
56d93bc
roidsec conflicts
Jclavo Dec 24, 2024
be05d96
sourceList
Jclavo Dec 24, 2024
b96403a
sinkList
Jclavo Dec 24, 2024
f6c1284
beita_com_beita_contact
Jclavo Dec 24, 2024
40393e0
fix
Jclavo Dec 24, 2024
7a3f784
cajino_baidu
Jclavo Dec 24, 2024
5ea6d89
chat_hook
Jclavo Dec 24, 2024
0a4ab14
chulia
Jclavo Dec 24, 2024
1960177
death_ring_materialflow
Jclavo Dec 24, 2024
abaf61e
rename template
Jclavo Dec 24, 2024
9548d0e
dsencrypt_samp
Jclavo Dec 24, 2024
eeef87f
rename template
Jclavo Dec 24, 2024
f90d00a
exprespam
Jclavo Dec 24, 2024
fddcd25
fakeappstore
Jclavo Dec 24, 2024
6d75247
fakebank_android_samp
Jclavo Dec 24, 2024
442c0cb
fakedaum
Jclavo Dec 24, 2024
a4ab1f0
fakemart
Jclavo Dec 24, 2024
0dcdba9
fakeplay
Jclavo Dec 25, 2024
e6aff13
faketaobao
Jclavo Dec 25, 2024
0867c38
godwon_samp
Jclavo Dec 25, 2024
2d38fdb
hummingbad_android_samp
Jclavo Dec 25, 2024
62d7ca1
jollyserv
Jclavo Dec 25, 2024
e001475
overlaylocker2_android_samp
Jclavo Dec 25, 2024
7983407
phospy
Jclavo Dec 25, 2024
7232f6f
proxy_samp
Jclavo Dec 25, 2024
6f64a3d
remote_control_smack
Jclavo Dec 25, 2024
1336f38
repane
Jclavo Dec 25, 2024
6b80332
roidsec
Jclavo Dec 25, 2024
e0731ca
samsapo
Jclavo Dec 25, 2024
9e6801f
save_me
Jclavo Dec 25, 2024
ee1f851
scipiex
Jclavo Dec 25, 2024
575994c
slocker_android_samp
Jclavo Dec 25, 2024
b7a7722
sms_google
Jclavo Dec 25, 2024
f675e96
sms_send_locker_qqmagic
Jclavo Dec 25, 2024
c204789
smssend_packageInstaller
Jclavo Dec 25, 2024
085dbe4
smssilience_fake_vertu
Jclavo Dec 25, 2024
1836fce
smsstealer_kysn_assassincreed_android_samp
Jclavo Dec 25, 2024
cb39d59
stels_flashplayer_android_update
Jclavo Dec 25, 2024
1f0a2e7
tetus
Jclavo Dec 25, 2024
57c4dfb
the_interview_movieshow
Jclavo Dec 25, 2024
d57ce37
threatjapan_uracto
Jclavo Dec 25, 2024
8f7679c
vibleaker_android_samp
Jclavo Dec 25, 2024
54535ef
vibleaker_android_samp
Jclavo Dec 25, 2024
45ef00d
remove list
Jclavo Dec 25, 2024
a3dcf4f
xbot_android_samp
Jclavo Dec 25, 2024
7b43b7e
update number of assertions
Jclavo Dec 26, 2024
638ac5b
extends FlowdroidSpec
Jclavo Dec 26, 2024
0ea9a2b
organize imports
Jclavo Dec 26, 2024
c43c171
typo
Jclavo Dec 26, 2024
b0ce4d5
rename to TaintBenchSpec
Jclavo Dec 29, 2024
8f616d5
fix test amount of leaks
Jclavo Dec 30, 2024
1f39fe7
add info about Taintbench
Jclavo Dec 30, 2024
fc58d73
add source
Jclavo Dec 30, 2024
090ca00
task info
Jclavo Dec 30, 2024
045942b
comments
Jclavo Dec 30, 2024
f41765c
some extra configurations
Jclavo Jan 17, 2025
e4f37d0
add metrics to taintbench results
Jclavo Jan 18, 2025
d5a24a3
wip: CASE II for Taintbench
Jclavo Jan 18, 2025
5fbca18
use - instead 0
Jclavo Jan 18, 2025
bd7902e
chat_hook
Jclavo Jan 18, 2025
a8ea58a
Metrics
Jclavo Jan 18, 2025
9f46d5c
add Metrics
Jclavo Jan 18, 2025
728897b
new TaintBenchSpec
Jclavo Jan 18, 2025
58370f1
chulia
Jclavo Jan 18, 2025
69d98dd
chat_hook
Jclavo Jan 18, 2025
8a6c710
set 0
Jclavo Jan 18, 2025
c562ba8
set 0
Jclavo Jan 18, 2025
8d7a370
death_ring_materialflow
Jclavo Jan 18, 2025
33b8dec
dsencrypt_samp
Jclavo Jan 18, 2025
63d6580
exprespam
Jclavo Jan 18, 2025
cc503a5
fakeappstore
Jclavo Jan 18, 2025
9be4bc7
exprespam
Jclavo Jan 18, 2025
876a0db
fakebank_android_samp
Jclavo Jan 18, 2025
46206b6
fakedaum
Jclavo Jan 18, 2025
bdae64f
fakemart
Jclavo Jan 18, 2025
984a256
fakeplay
Jclavo Jan 18, 2025
225ddb1
faketaobao
Jclavo Jan 18, 2025
f6c7ae5
godwon_samp
Jclavo Jan 18, 2025
490620b
hummingbad_android_samp
Jclavo Jan 18, 2025
bee457b
jollyserv
Jclavo Jan 18, 2025
581b672
overlay_android_samp
Jclavo Jan 18, 2025
0f6ec66
overlaylocker2_android_samp
Jclavo Jan 18, 2025
a245a38
phospy
Jclavo Jan 18, 2025
71887a4
proxy_samp
Jclavo Jan 18, 2025
160fe06
remote_control_smack
Jclavo Jan 18, 2025
1f2d1e2
repane
Jclavo Jan 18, 2025
7949308
Roidsec
Jclavo Jan 18, 2025
6babf84
samsapo
Jclavo Jan 18, 2025
b7485fb
save_me
Jclavo Jan 18, 2025
e8058ed
scipiex
Jclavo Jan 18, 2025
47e4bf0
slocker_android_samp
Jclavo Jan 18, 2025
bb9395c
sms_google
Jclavo Jan 18, 2025
2c5dd38
sms_send_locker_qqmagic
Jclavo Jan 18, 2025
66634fd
smssend_packageInstaller
Jclavo Jan 18, 2025
401d044
smssilience_fake_vertu
Jclavo Jan 18, 2025
fca29ee
smsstealer_kysn_assassincreed_android_samp
Jclavo Jan 18, 2025
5ef41b2
stels_flashplayer_android_update
Jclavo Jan 18, 2025
15f0159
tetus
Jclavo Jan 18, 2025
189108a
the_interview_movieshow
Jclavo Jan 18, 2025
f49faa4
threatjapan_uracto
Jclavo Jan 18, 2025
97fa479
vibleaker_android_samp
Jclavo Jan 18, 2025
a7519a6
xbot_android_samp
Jclavo Jan 18, 2025
d31e1bf
final metrics
Jclavo Jan 18, 2025
7bfa63c
add TP and TN
Jclavo Jan 18, 2025
b89c52d
Experiment 2 - TB2
Jclavo Jan 19, 2025
9642842
method to compute metrics
Jclavo Jan 19, 2025
879f7c8
TAINTBENCH introduction
Jclavo Jan 19, 2025
8564f04
metrics2
Jclavo Jan 19, 2025
8c52d4f
refactor metrics path
Jclavo Jan 19, 2025
179e14b
rename to computeMetricsByCriterions
Jclavo Jan 19, 2025
cd22328
rename to computeMetricsByResults
Jclavo Jan 19, 2025
094d077
CaseStudy2
Jclavo Jan 19, 2025
b725305
CASE STUDY 1
Jclavo Jan 19, 2025
5952e34
fix table
Jclavo Jan 19, 2025
c7a9b9a
backflash
Jclavo Jan 19, 2025
2e9291a
beita_com_beita_contact
Jclavo Jan 19, 2025
efa620f
backflash FP
Jclavo Jan 19, 2025
5cefb40
cajino_baidu
Jclavo Jan 19, 2025
f498657
chat_hook
Jclavo Jan 19, 2025
ed9fa38
chulia
Jclavo Jan 19, 2025
078ef3f
death_ring_materialflow
Jclavo Jan 19, 2025
975d056
dsencrypt_samp
Jclavo Jan 19, 2025
a28fcf6
exprespam
Jclavo Jan 19, 2025
305942d
fakeappstore
Jclavo Jan 19, 2025
1d2bf1f
fakebank_android_samp
Jclavo Jan 19, 2025
4fe3639
fakedaum
Jclavo Jan 19, 2025
9a41961
fakemart
Jclavo Jan 19, 2025
e853ce0
fakeplay
Jclavo Jan 19, 2025
6ce5a9e
faketaobao
Jclavo Jan 19, 2025
2a83115
godwon_samp
Jclavo Jan 19, 2025
a5346f0
hummingbad_android_samp
Jclavo Jan 19, 2025
2a6429f
jollyserv
Jclavo Jan 19, 2025
ba8863a
overlay_android_samp
Jclavo Jan 19, 2025
873935b
overlaylocker2_android_samp
Jclavo Jan 19, 2025
e642e89
phospy
Jclavo Jan 19, 2025
c9cf24e
proxy_samp
Jclavo Jan 19, 2025
afc77be
remote_control_smack
Jclavo Jan 19, 2025
05aa8c3
repane
Jclavo Jan 19, 2025
d949a39
Roidsec
Jclavo Jan 19, 2025
41e3c31
samsapo
Jclavo Jan 19, 2025
27451f5
save_me
Jclavo Jan 19, 2025
6237529
scipiex
Jclavo Jan 19, 2025
2979a6a
slocker_android_samp
Jclavo Jan 19, 2025
2a1102c
sms_google
Jclavo Jan 19, 2025
3901602
sms_send_locker_qqmagic
Jclavo Jan 19, 2025
7f616c6
smssend_packageInstaller
Jclavo Jan 19, 2025
9f2b902
smssilience_fake_vertu
Jclavo Jan 19, 2025
2687cce
smsstealer_kysn_assassincreed_android_samp
Jclavo Jan 19, 2025
84bfae4
stels_flashplayer_android_update
Jclavo Jan 19, 2025
4890076
tetus
Jclavo Jan 19, 2025
5722317
the_interview_movieshow
Jclavo Jan 19, 2025
a239244
threatjapan_uracto
Jclavo Jan 19, 2025
0ab4182
vibleaker_android_samp
Jclavo Jan 19, 2025
bac7a52
xbot_android_samp
Jclavo Jan 19, 2025
734d331
actual
Jclavo Jan 19, 2025
ff13190
TP
Jclavo Jan 19, 2025
fe295f8
FP
Jclavo Jan 19, 2025
96d7a99
metrics
Jclavo Jan 19, 2025
d65801e
metrics
Jclavo Jan 19, 2025
de78b80
JSVFA metrics
Jclavo Jan 19, 2025
0ff54fc
FLOWDROID metrics
Jclavo Jan 19, 2025
96c01d2
comment tests
Jclavo Jan 19, 2025
bb74a2e
CASE STUDY explanation
Jclavo Jan 19, 2025
06f02bc
wip
Jclavo Jan 19, 2025
d66d37d
rename to EXPERIMENT
Jclavo Jan 19, 2025
32d1e71
rename files
Jclavo Jan 19, 2025
d26f46c
create separate files for details
Jclavo Feb 6, 2025
8d1a79a
securibench metrics
Jclavo Feb 6, 2025
65974f4
Merge branch 'develop' of https://github.com/PAMunb/svfa into task/in…
Jclavo Feb 6, 2025
2dcdf91
remove unnecessary comments
Jclavo Feb 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 87 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,30 +136,110 @@ To have detailed information about each group of tests run, [see here.](new-metr
| JSVFA 2.0 | 0.91 | 0.76 | 0.83 |
| Basic | 0.93 | 0.97 | 0.95 |

### Taintbench: (WIP)
### TAINTBENCH:

[Taintbench](https://github.com/TaintBench/TaintBench/releases/download/TaintBenchSuite/TaintBench.zip) contains a set o Android Apks that are old malware apps.
We have created a file `taintbench.properties` in `src/test/resources` to set the configurations.
[TAINTBENCH](https://taintbench.github.io/) is a benchmark that contains a [set of old malware Android Apks](https://github.com/TaintBench/TaintBench/releases/download/TaintBenchSuite/TaintBench.zip) ,
and it is introduced by [Paper: TaintBench: Automatic real-world malware benchmarking of Android taint analyses](https://doi.org/10.1007/s10664-021-10013-5),
which in its result section presents six experiments to answer one of its RQ: *How effective are taint analysis tools on TaintBench compared to DroidBench*,
where FLOWDROID and AMANDROID as the chosen tools.

> failed: ?, passed: 1, ignored: ? of 39 test (?%)
In the next sections, we will focus in **Experiment 2** and **Experiment 3** and use our tool (JSVFA) to reproduce them.
After that, we will compare the already computed results for FLOWDROID to our results.

- [Roidsec]
- [ ]
- [ ]
- The result for each APK tested using JSVFA are presented in a table that contains the following information.
- **Expected:** The amount of taint flows presented by TAINTBENCH
- **Actual:** The amount of taint flows detected by JSVFA
- **Status:** If the test PASS OR FAIL
- **TP:** True Positive
- **FP:** False Positive
- **Precision:** TP/(TP + FP)
- **Recall:** TP/P
- **F-score:** (2 x Precision x Recall)/(Precision + Recall)
- We have created a file `taintbench.properties` in `src/test/resources` to set the configurations

**Disclaimer**: Although TAINTBENCH contains 203 expected [taint flows](https://taintbench.github.io/taintbenchSuite/),
we have decided to use only 186 expected cases because the mentioned paper, uses as a reference, works with those amounts.

#### EXPERIMENT I

This case emulates **Experiment 2 - TB2** that states:

>All tools are configured with sources and sinks defined in benchmark suite.

The mentioned sources and sinks can be found in [TB_SourcesAndSinks](https://github.com/TaintBench/TaintBench/blob/master/TB_SourcesAndSinks.txt),
and we have stored them in `src/test/scala/br/unb/cic/android/TaintBenchSpec.scala`.

As a result, we got `37 failed and 2 passed of 39 tests` and comparing to FLOWDROID we detected the same amount of `TP(41)`
but less amount of `FP(9)` and about metrics, we got a better `precision(0.82)`, the same `recall(0.22)` value
and a slightly better `F-score(0.35)`.

- JSVFA metrics, to have detailed information about each group of tests run, [see here.](taintbench-experiment-I.md)

| Expected | Actual | TP | FP | Precision | Recall | F-score |
|:--------:|:------:|:--:|:--:|:---------:|:------:|:--------:|
| 186 | 50 | 41 | 9 | 0.82 | 0.22 | 0.35 |

- FLOWDROID metrics from [Paper](https://doi.org/10.1007/s10664-021-10013-5)

| Expected | Actual | TP | FP | Precision | Recall | F-score |
|:--------:|:------:|:--:|:--:|:---------:|:------:|:--------:|
| 186 | 55 | 41 | 14 | 0.75 | 0.22 | 0.34 |

##### Observation
- From the 37 failing tests, 28 of them reported zero flows.


#### EXPERIMENT II

This case emulates **Experiment 3 - TB3** that configures:

>For each benchmark app, a list of sources and sinks defined in this app is used to
configure all tools. Each tool analyzes each benchmark app with the associated list
of sources and sinks

The mentioned lists can be found in https://taintbench.github.io/taintbenchSuite/, and we have stored them by individual
files in `src/test/scala/br/unb/cic/android/specs`.

As a result, we got `38 failed and 1 passed of 39 test` and comparing to FLOWDROID we detect a several better amount of `TP(135)`
but also a several amount of `FP(318)` and about metric, we got a significant less `precision(0.30)` due to the high amount of FP; however,
a good `recall(0.73)` value and a better `F-score(0.42)`.

- JSVFA metrics, to have detailed information about each group of tests run, [see here.](taintbench-experiment-II.md)


| Expected | Actual | TP | FP | Precision | Recall | F-score |
|:--------:|:------:|:---:|:---:|:---------:|:------:|:-------:|
| 186 | 453 | 135 | 318 | 0.30 | 0.73 | 0.42 |


- FLOWDROID metrics from Paper https://doi.org/10.1007/s10664-021-10013-5

| Expected | Actual | TP | FP | Precision | Recall | F-score |
|:--------:|:------:|:--:|:--:|:---------:|:------:|:-------:|
| 186 | 57 | 43 | 14 | 0.75 | 0.23 | 0.35 |


##### Observation
- We got a big amount of FP.

## Tasks
### WIP
- [ ] Create Git Action flow.

### TO-DO
- [ ] Finish integration of Taintbench.
- [ ] Check if each test in Securibench has the right expected values.
- [ ] Add set up project documentation.
- [ ] Integrate Securibench as a submodule.
- [ ] Compute metrics for Securibench results.
- [ ] Fix bugs for Securibench in folders
- [ ] Datastructure
- [ ] Factory
- [ ] Session
- [ ] Strong Update
- [ ] Aliasing

### DONE
- [X] Integration of Taintbench.

[//]: # (## License)
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ trait AndroidSootConfiguration extends SootConfiguration {

def platform(): String
override def configureSoot(): Unit = {
// Set up InfoflowAndroidConfiguration
val config = new InfoflowAndroidConfiguration
config.setCallgraphAlgorithm(InfoflowConfiguration.CallgraphAlgorithm.CHA)
config.setCodeEliminationMode(
Expand All @@ -24,8 +25,8 @@ trait AndroidSootConfiguration extends SootConfiguration {
config.setIgnoreFlowsInSystemPackages(true)
config.setExcludeSootLibraryClasses(true)

// Create the data flow analyzer
val flowDroid = new SetupApplication(config)

flowDroid.constructCallgraph()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package br.unb.cic.soot.svfa.configuration

import soot._
import soot.jimple.infoflow.InfoflowConfiguration
import soot.jimple.infoflow.android.config.SootConfigForAndroid
import soot.jimple.infoflow.android.{InfoflowAndroidConfiguration, SetupApplication}
import soot.options.Options

import java.io.File
import java.util.Collections

trait AndroidSootConfiguration2 extends SootConfiguration {

def apk: String

def platform(): String

def callGraph(): CG = SPARK

def applicationClassPath(): List[String] = List("target/scala-2.12/test-classes", System.getProperty("user.home")+"/.m2/repository/javax/servlet/javax.servlet-api/3.0.1/javax.servlet-api-3.0.1.jar")

def sootClassPath(): String = ""

override def configureSoot() {
// Do InfoflowAndroidConfiguration
val config = new InfoflowAndroidConfiguration
config.setCallgraphAlgorithm(InfoflowConfiguration.CallgraphAlgorithm.SPARK)
config.setCodeEliminationMode(
InfoflowConfiguration.CodeEliminationMode.NoCodeElimination
)
config.getAnalysisFileConfig.setAndroidPlatformDir(platform)
config.getAnalysisFileConfig.setTargetAPKFile(apk)

// Do Soot Configuration
G.reset()
soot.options.Options.v().set_allow_phantom_refs(true);
soot.options.Options.v().set_output_format(soot.options.Options.output_format_none);
// soot.options.Options.v().set_process_dir(Collections.singletonList(apk));
// soot.options.Options.v().set_force_android_jar(platform());
soot.options.Options.v().set_src_prec(soot.options.Options.src_prec_apk_class_jimple);
soot.options.Options.v().set_keep_line_number(false);
soot.options.Options.v().set_keep_offset(false);
soot.options.Options.v().set_throw_analysis(soot.options.Options.throw_analysis_dalvik);
soot.options.Options.v().set_process_multiple_dex(true);
soot.options.Options.v().set_whole_program(true);

// Soot config for Android
val sootConfig = new SootConfigForAndroid();
sootConfig.setSootOptions(soot.options.Options.v(), config);

// Create the data flow analyzer
val analyzer = new SetupApplication(config);
analyzer.setSootConfig(sootConfig);
analyzer.constructCallgraph();
}
def configureSoot2() {
// val config = new InfoflowAndroidConfiguration
// config.setCallgraphAlgorithm(InfoflowConfiguration.CallgraphAlgorithm.SPARK)
// config.setCodeEliminationMode(
// InfoflowConfiguration.CodeEliminationMode.NoCodeElimination
// )
// config.getAnalysisFileConfig.setAndroidPlatformDir(platform)
// config.getAnalysisFileConfig.setTargetAPKFile(apk)
//
// val flowDroid = new SetupApplication(config)
//
// flowDroid.constructCallgraph()

// val androidJar = config.getAnalysisFileConfig.getAndroidPlatformDir
// val apkFileLocation = config.getAnalysisFileConfig.getTargetAPKFile

// Clean up any old Soot instance we may have
// val config = new InfoflowAndroidConfiguration
G.reset

Options.v.set_no_bodies_for_excluded(true)
Options.v.set_allow_phantom_refs(true)
Options.v.set_output_format(Options.output_format_none)
Options.v.set_whole_program(true)
Options.v.set_process_dir(Collections.singletonList(apk))
Options.v.set_force_android_jar(platform())
Options.v.set_src_prec(Options.src_prec_apk_class_jimple)
Options.v.set_keep_offset(false)
Options.v.set_keep_line_number(true)
Options.v.set_throw_analysis(Options.throw_analysis_dalvik)
Options.v.set_process_multiple_dex(true)
Options.v.set_ignore_resolution_errors(true)

// Set soot phase option if original names should be used
Options.v.setPhaseOption("jb", "use-original-names:true")

// Set the Soot configuration options. Note that this will needs to be
// done before we compute the classpath.

Options
.v()
.set_soot_classpath(
sootClassPath() + File.pathSeparator + pathToJCE() + File.pathSeparator + pathToRT()
)
Main.v.autoSetOptions()
configureCallGraphPhase()

// Load whatever we need
Scene.v.loadNecessaryClasses()

// Make sure that we have valid Jimple bodies
PackManager.v.getPack("wjpp").apply()

// Patch the callgraph to support additional edges. We do this now,
// because during callback discovery, the context-insensitive callgraph
// algorithm would flood us with invalid edges.
// val configuration = new InfoflowAndroidConfiguration();
// configuration.setSootIntegrationMode(SootIntegrationMode.UseExistingInstance);
// val flowDroid = new SetupApplication(configuration)
// flowDroid.constructCallgraph()
}


def configureCallGraphPhase() {
callGraph() match {
case CHA => Options.v().setPhaseOption("cg.cha", "on")
case SPARK => {
Options.v().setPhaseOption("cg.spark", "on")
// Options.v().setPhaseOption("cg.spark", "cs-demand:true")
// Options.v().setPhaseOption("cg.spark", "string-constants:true")
Options.v.setPhaseOption("cg.spark", "string-constants:true")
}
case SPARK_LIBRARY => {
Options.v().setPhaseOption("cg.spark", "on")
Options.v().setPhaseOption("cg", "library:any-subtype")
}
}
}
}
Loading