# Security Implications of ADB Debugging for scrcpy: A Complete Technical Analysis

> Explore the security implications of ADB debugging for scrcpy. Understand how a compromised host can access your Android device and protect your data.

- Repository: [Genymobile/scrcpy](https://github.com/Genymobile/scrcpy)
- Tags: deep-dive
- Published: 2026-02-25

---

**Enabling USB debugging for scrcpy grants the host computer full ADB privileges, creating a trust boundary where a compromised host can execute arbitrary code, capture the screen, or inject input on the connected Android device.**

**scrcpy** is a lightweight screen mirroring tool developed by Genymobile that relies entirely on the Android Debug Bridge (ADB) to communicate with Android devices. Because scrcpy does not implement additional sandboxing beyond what ADB provides, understanding the security implications of ADB debugging is essential for safe deployment. This analysis examines the specific attack vectors present in the scrcpy source code and provides actionable mitigation strategies.

## How scrcpy Leverages ADB Privileges

scrcpy operates as a thin client that mirrors an Android device on a computer, with all communication traversing the ADB daemon. According to the Genymobile/scrcpy source code, the tool functions as an **ADB client** that pushes a Java server to the device (`/data/local/tmp/scrcpy-server.jar`), establishes socket connections via port forwarding, and issues shell commands to control the device.

The main client logic resides in [`app/src/server.c`](https://github.com/Genymobile/scrcpy/blob/main/app/src/server.c), where the `push_server()` function (lines 58-68) pushes the server JAR to the device using `sc_adb_push`. Because ADB operates with elevated privileges on devices with **Developer options → USB debugging** enabled, scrcpy inherits these capabilities automatically. The server JAR executes with the same privileges as the ADB shell, granting the host computer substantial control over the target device.

## Critical Attack Vectors in scrcpy's ADB Integration

### Server Push and Arbitrary Code Execution

In `app/src/server.c#L58-L68`, the `push_server()` function transfers the scrcpy server to `/data/local/tmp/` using `sc_adb_push`. The device trusts any file received via `adb push`, meaning a malicious host that replaces the legitimate JAR with a modified version can execute arbitrary code on the device. This represents a **supply chain attack vector** where the host's file system integrity becomes critical to device security.

### Command Injection Risks

scrcpy uses `sc_adb_execute()` (defined in `app/src/adb/adb.c#L228-229`) to run shell commands on the device, including operations for TCP/IP toggling and device configuration (referenced at `server.c#L456`). To mitigate shell injection, the codebase implements `validate_string()` in `server.c#L89-100`, which sanitizes command-line parameters before execution. However, any vulnerability in this validation logic could allow an attacker to run arbitrary shell commands on the device.

### Port Forwarding Exposure

scrcpy creates local UNIX sockets on the host and forwards them to the device using `sc_adb_forward` (`app/src/adb/adb.c#L249-251`) and reverse tunnels via `sc_adb_reverse` (`app/src/adb/adb_tunnel.c#L22-23`). These forwarded ports expose the device’s internal services—including the video stream socket—to the host’s network stack. If the host machine is compromised, an attacker can capture the video stream or inject control messages by connecting to these local ports.

### TCP/IP Mode Network Exposure

When using the `--tcpip` flag, scrcpy automatically enables *adb over network* on the device, documented in [`doc/connection.md`](https://github.com/Genymobile/scrcpy/blob/main/doc/connection.md) (lines 70-78). This operation internally executes `adb tcpip 5555`, opening the ADB daemon on port 5555 to the local network. An attacker on the same LAN can then connect to the device without physical access, bypassing the USB cable requirement and expanding the attack surface from local to network-based threats.

## Device Authentication and Trust Boundaries

### Device Selection via ANDROID_SERIAL

scrcpy reads the `ANDROID_SERIAL` environment variable or executes `adb devices` to select a target device, as documented in [`doc/connection.md`](https://github.com/Genymobile/scrcpy/blob/main/doc/connection.md) (lines 5-33). An attacker who controls the host environment can manipulate this variable to force scrcpy to connect to an arbitrary device visible via ADB, potentially intercepting screenshots or redirecting input to a malicious target.

### Input Injection and Media Projection Permissions

While the scrcpy server JAR runs as a normal app without root access, it requests **media projection** and **input injection** capabilities that require one-time user approval. Once authorized, any process capable of communicating with the scrcpy server—such as other local programs on the host—can capture the screen or inject input events. This occurs because the server trusts the local socket forwarded by ADB, creating a privilege escalation path from host user to device control.

### Cleanup and Persistent Exposure

scrcpy attempts to clean up resources by calling `sc_adb_kill_server()` on exit (`app/src/server.c#L936`), which removes forwarded sockets. However, if scrcpy crashes or is terminated abruptly (`SIGKILL`), these forwarded ports may remain open indefinitely, leaving the device exposed until the user manually restarts ADB or reboots the device.

## Practical Security Hardening for scrcpy

Use these code examples to minimize your attack surface when operating scrcpy.

**Basic USB-only connection (least risky):**

```bash

# Connect device via USB only, no network exposure

scrcpy

```

**Explicitly disable TCP/IP mode before connecting:**

```bash

# Force ADB back to USB mode to prevent accidental network exposure

adb usb
scrcpy

```

**Manual TCP/IP with controlled network access:**

```bash

# Only enable if your network is trusted and secured

adb tcpip 5555
adb connect 192.168.1.42:5555
scrcpy

```

**Verify and restrict port forwarding:**

```bash

# Check existing forwards that might expose the device

adb forward --list

# Remove all forwards when done

adb forward --remove-all

```

## Summary

- **ADB is the trust anchor**: scrcpy does not add extra sandboxing; it fully trusts the ADB connection, inheriting all associated privileges and risks.
- **Server push vulnerability**: The `push_server()` mechanism in [`server.c`](https://github.com/Genymobile/scrcpy/blob/main/server.c) allows arbitrary code execution if the host serves a malicious JAR.
- **Network exposure**: Enabling ADB over Wi-Fi via `--tcpip` opens port 5555, allowing any device on the same LAN to attempt ADB connections.
- **Port forwarding risks**: Local sockets forwarded via `sc_adb_forward` and `sc_adb_reverse` expose video and control channels to the host, enabling eavesdropping if the host is compromised.
- **Cleanup failures**: Abrupt termination may leave forwarded ports open, requiring manual intervention to secure the device.

## Frequently Asked Questions

### Does scrcpy require root access on the Android device?

No, scrcpy does not require root access. The server runs as a regular application using ADB shell permissions, but it can request media projection and input injection capabilities once authorized by the user. These permissions grant significant control without requiring root, as implemented in the server logic at [`app/src/server.c`](https://github.com/Genymobile/scrcpy/blob/main/app/src/server.c).

### Can someone hack my phone through scrcpy if they are on the same Wi-Fi network?

Yes, if you enable **ADB over TCP/IP** using `scrcpy --tcpip` or `adb tcpip 5555`, the ADB daemon listens on port 5555. Anyone on the same network can attempt to connect using `adb connect <your-ip>:5555`. While ADB requires RSA key authentication for initial pairing, a persistent attacker could potentially exploit this exposure, as documented in the connection flow at [`doc/connection.md`](https://github.com/Genymobile/scrcpy/blob/main/doc/connection.md).

### How does scrcpy prevent command injection when executing ADB shell commands?

scrcpy mitigates shell injection through the `validate_string()` function located at `server.c#L89-100`, which sanitizes parameters passed to `sc_adb_execute()` (`adb.c#L228-229`). However, this validation is the primary defense line; any bug in this sanitization logic could expose the device to arbitrary command execution from a malicious host.

### What happens to port forwards if scrcpy crashes unexpectedly?

If scrcpy terminates abnormally without executing the cleanup routine `sc_adb_kill_server()` at `server.c#L936`, the forwarded ports created by `sc_adb_forward` and `sc_adb_reverse` may remain active. This leaves the device's scrcpy socket exposed on the host until you manually run `adb forward --remove-all` or restart the ADB daemon.