@@ -23,22 +23,38 @@ type Application struct {
2323 Debuggable string `xml:"http://schemas.android.com/apk/res/android debuggable,attr"`
2424 AllowBackup string `xml:"http://schemas.android.com/apk/res/android allowBackup,attr"`
2525 NetworkSecurityConfig string `xml:"http://schemas.android.com/apk/res/android networkSecurityConfig,attr"`
26+ UsesCleartextTraffic string `xml:"http://schemas.android.com/apk/res/android usesCleartextTraffic,attr"`
27+ FullBackupContent string `xml:"http://schemas.android.com/apk/res/android fullBackupContent,attr"`
2628 Activities []Component `xml:"activity"`
2729 Services []Component `xml:"service"`
2830 Receivers []Component `xml:"receiver"`
31+ Providers []Component `xml:"provider"`
2932}
3033
31- // Component represents an activity, service, or receiver .
34+ // Component represents an activity, service, receiver, or provider .
3235type Component struct {
33- Name string `xml:"http://schemas.android.com/apk/res/android name,attr"`
34- Exported string `xml:"http://schemas.android.com/apk/res/android exported,attr"`
36+ Name string `xml:"http://schemas.android.com/apk/res/android name,attr"`
37+ Exported string `xml:"http://schemas.android.com/apk/res/android exported,attr"`
38+ Permission string `xml:"http://schemas.android.com/apk/res/android permission,attr"`
39+ IntentFilters []IntentFilter `xml:"intent-filter"`
40+ }
41+
42+ // IntentFilter represents an intent-filter within a component.
43+ type IntentFilter struct {
44+ Actions []Action `xml:"action"`
45+ }
46+
47+ // Action represents an action within an intent-filter.
48+ type Action struct {
49+ Name string `xml:"http://schemas.android.com/apk/res/android name,attr"`
3550}
3651
3752// SecurityFinding represents a security issue found in the manifest or resources.
3853type SecurityFinding struct {
3954 Type string
4055 Description string
4156 Severity string
57+ MASVS string
4258}
4359
4460var dangerousPermissions = map [string ]bool {
@@ -73,59 +89,106 @@ func AnalyzeManifest(manifestPath string) ([]SecurityFinding, error) {
7389
7490 var findings []SecurityFinding
7591
76- // 1. Dangerous Permissions
92+ // 1. Dangerous Permissions (MASVS-PRIVACY)
7793 for _ , p := range manifest .Permissions {
7894 if dangerousPermissions [p .Name ] {
7995 findings = append (findings , SecurityFinding {
8096 Type : "Permission" ,
8197 Description : "Dangerous permission requested: " + p .Name ,
8298 Severity : "medium" ,
99+ MASVS : "MASVS-PRIVACY-1" ,
83100 })
84101 }
85102 }
86103
87- // 2. Debuggable
104+ // 2. Debuggable (MASVS-RESILIENCE)
88105 if manifest .Application .Debuggable == "true" {
89106 findings = append (findings , SecurityFinding {
90107 Type : "Manifest" ,
91108 Description : "Application is debuggable" ,
92109 Severity : "high" ,
110+ MASVS : "MASVS-RESILIENCE-2" ,
93111 })
94112 }
95113
96- // 3. AllowBackup
114+ // 3. AllowBackup (MASVS-STORAGE)
97115 if manifest .Application .AllowBackup == "true" || manifest .Application .AllowBackup == "" {
98116 findings = append (findings , SecurityFinding {
99117 Type : "Manifest" ,
100118 Description : "Application allows backup (allowBackup should be explicitly false)" ,
101119 Severity : "medium" ,
120+ MASVS : "MASVS-STORAGE-2" ,
102121 })
103122 }
104123
105- // 4. Network Security Config
124+ // 4. Cleartext Traffic (MASVS-NETWORK)
125+ if manifest .Application .UsesCleartextTraffic == "true" || manifest .Application .UsesCleartextTraffic == "" {
126+ findings = append (findings , SecurityFinding {
127+ Type : "Network" ,
128+ Description : "Application allows cleartext traffic (HTTP). Set usesCleartextTraffic to false." ,
129+ Severity : "high" ,
130+ MASVS : "MASVS-NETWORK-1" ,
131+ })
132+ }
133+
134+ // 5. Network Security Config
106135 if manifest .Application .NetworkSecurityConfig != "" {
107136 findings = append (findings , SecurityFinding {
108137 Type : "Manifest" ,
109138 Description : "Network Security Configuration is defined: " + manifest .Application .NetworkSecurityConfig ,
110139 Severity : "info" ,
140+ MASVS : "MASVS-NETWORK-1" ,
141+ })
142+ }
143+
144+ // 6. Full Backup Content
145+ if manifest .Application .FullBackupContent == "" && manifest .Application .AllowBackup != "false" {
146+ findings = append (findings , SecurityFinding {
147+ Type : "Manifest" ,
148+ Description : "Full backup content not specified. Define android:fullBackupContent to control backup" ,
149+ Severity : "low" ,
150+ MASVS : "MASVS-STORAGE-2" ,
111151 })
112152 }
113153
114- // 5. Exported Components
115- checkExported (manifest .Application .Activities , "Activity" , & findings )
116- checkExported (manifest .Application .Services , "Service" , & findings )
117- checkExported (manifest .Application .Receivers , "Receiver" , & findings )
154+ // 7. Exported Components (MASVS-PLATFORM)
155+ checkExportedWithIntentFilter (manifest .Application .Activities , "Activity" , & findings )
156+ checkExportedWithIntentFilter (manifest .Application .Services , "Service" , & findings )
157+ checkExportedWithIntentFilter (manifest .Application .Receivers , "Receiver" , & findings )
158+ checkExportedWithIntentFilter (manifest .Application .Providers , "Provider" , & findings )
118159
119160 return findings , nil
120161}
121162
122- func checkExported (components []Component , componentType string , findings * []SecurityFinding ) {
163+ func checkExportedWithIntentFilter (components []Component , componentType string , findings * []SecurityFinding ) {
123164 for _ , c := range components {
165+ // If explicitly exported=true
124166 if c .Exported == "true" {
167+ // Check if it has permission protection
168+ if c .Permission == "" {
169+ * findings = append (* findings , SecurityFinding {
170+ Type : componentType ,
171+ Description : fmt .Sprintf ("Exported %s without permission: %s" , componentType , c .Name ),
172+ Severity : "high" ,
173+ MASVS : "MASVS-PLATFORM-1" ,
174+ })
175+ } else {
176+ * findings = append (* findings , SecurityFinding {
177+ Type : componentType ,
178+ Description : fmt .Sprintf ("Exported %s found (with permission): %s" , componentType , c .Name ),
179+ Severity : "info" ,
180+ MASVS : "MASVS-PLATFORM-1" ,
181+ })
182+ }
183+ }
184+
185+ // If component has intent-filter, it's implicitly exported (Android < 12)
186+ if len (c .IntentFilters ) > 0 && c .Exported == "" {
125187 * findings = append (* findings , SecurityFinding {
126188 Type : componentType ,
127- Description : fmt .Sprintf ("Exported %s found : %s" , componentType , c .Name ),
189+ Description : fmt .Sprintf ("%s with intent-filter is implicitly exported : %s (set exported explicitly) " , componentType , c .Name ),
128190 Severity : "medium" ,
191+ MASVS : "MASVS-PLATFORM-1" ,
129192 })
130193 }
131194 }
0 commit comments