@@ -6,6 +6,7 @@ import com.celzero.bravedns.service.PersistentState
66import io.mockk.coVerify
77import io.mockk.every
88import io.mockk.mockk
9+ import io.mockk.spyk
910import kotlinx.coroutines.CoroutineScope
1011import kotlinx.coroutines.Dispatchers
1112import org.junit.Assert.assertEquals
@@ -200,28 +201,72 @@ class VpnControlReceiverTest {
200201 // ── caller identity resolution ───────────────────────────────────────────
201202
202203 @Test
203- fun `default resolver ignores spoofed sender extra and rejects when os identity is absent` () {
204+ @Config(sdk = [34 ])
205+ fun `default resolver uses allowlisted sender extra when os identity is absent` () {
204206 every { persistentState.appTriggerPackages } returns " com.trusted.app"
205207 every { persistentState.wgTaskerAutomationEnabled } returns true
206208 receiver.callerResolver = { c, i -> receiver.defaultCallerResolver(c, i) }
207209 val intent = Intent (VpnControlReceiver .ACTION_WG_PAUSE ).apply {
208- // spoofed extra naming an allowlisted package must not grant trust
209210 putExtra(VpnControlReceiver .EXTRA_SENDER , " com.trusted.app" )
210211 putExtra(VpnControlReceiver .EXTRA_WG_IDS , " 1" )
211212 }
212213 receiver.onReceive(context, intent)
214+ coVerify(exactly = 1 ) { wgCommands.pause(listOf (1 )) }
215+ }
216+
217+ @Test
218+ @Config(sdk = [34 ])
219+ fun `default resolver rejects missing malformed and untrusted sender extras` () {
220+ every { persistentState.appTriggerPackages } returns " com.trusted.app"
221+ every { persistentState.wgTaskerAutomationEnabled } returns true
222+ receiver.callerResolver = { c, i -> receiver.defaultCallerResolver(c, i) }
223+
224+ listOf<String ?>(null , " " , " com.untrusted.app" ).forEach { sender ->
225+ val intent = Intent (VpnControlReceiver .ACTION_WG_PAUSE ).apply {
226+ if (sender != null ) {
227+ putExtra(VpnControlReceiver .EXTRA_SENDER , sender)
228+ }
229+ putExtra(VpnControlReceiver .EXTRA_WG_IDS , " 1" )
230+ }
231+ receiver.onReceive(context, intent)
232+ }
233+
213234 coVerify(exactly = 0 ) { wgCommands.pause(any()) }
214235 }
215236
216237 @Test
217- fun `default resolver returns null on spoofed extra when no os identity is stamped` () {
238+ @Config(sdk = [34 ])
239+ fun `default resolver gives os package identity precedence over sender extra` () {
240+ val osIdentityReceiver = spyk(receiver)
241+ osIdentityReceiver.wgCommands = wgCommands
242+ osIdentityReceiver.callerResolver = { c, i ->
243+ osIdentityReceiver.defaultCallerResolver(c, i)
244+ }
245+ every { osIdentityReceiver.sentFromPackage } returns " com.os.app"
246+ every { persistentState.appTriggerPackages } returns " com.trusted.app"
247+ every { persistentState.wgTaskerAutomationEnabled } returns true
248+ val intent = Intent (VpnControlReceiver .ACTION_WG_PAUSE ).apply {
249+ putExtra(VpnControlReceiver .EXTRA_SENDER , " com.trusted.app" )
250+ putExtra(VpnControlReceiver .EXTRA_WG_IDS , " 1" )
251+ }
252+
253+ osIdentityReceiver.onReceive(context, intent)
254+
255+ coVerify(exactly = 0 ) { wgCommands.pause(any()) }
256+ }
257+
258+ @Test
259+ @Config(sdk = [34 ])
260+ fun `default resolver uses package resolved from os uid before sender extra` () {
261+ val osIdentityReceiver = spyk(receiver)
262+ every { osIdentityReceiver.sentFromPackage } returns null
263+ every { osIdentityReceiver.sentFromUid } returns 1234
264+ every { context.packageManager.getPackagesForUid(1234 ) } returns arrayOf(" com.os.app" )
218265 val intent = Intent (VpnControlReceiver .ACTION_STOP ).apply {
219266 putExtra(VpnControlReceiver .EXTRA_SENDER , " com.trusted.app" )
220267 }
221- // on the Robolectric SDK no OS sender identity is stamped; the spoofed extra must not
222- // be honored even though it names an allowlisted package
223- val resolved = receiver.defaultCallerResolver(context, intent)
224- assertEquals(null , resolved)
268+
269+ assertEquals(" com.os.app" , osIdentityReceiver.defaultCallerResolver(context, intent))
225270 }
226271
227272 @Test
0 commit comments