Clutch: Cellular Security Monitor

Leave your phone at home. That's the advice. It's not always safe, not always practical, and not always right. Clutch was built around a better question: what if the device told you when the cellular layer stopped behaving like background infrastructure?

The advice is always the same. Leave your phone at home. Leave it in the hotel. Put it in a Faraday bag. Fly dark.

That advice comes from people who have never had to choose between carrying a camera and their safety. Between documentation and operational security. Between being present with a device and being present without one. It is correct in the abstract. It fails in the field.

I was arrested at a protest in 2002 or 2003 — one of the largest in New York City history, the kind of crowd that filled midtown in every direction and made the news cycle stop. Pre-smartphone era. I had a film camera. They took it when they took me. Gave it back when they released me. I developed the film after.

The photographs survived.

That experience taught something the security community often misses in their "leave the phone at home" lectures: governments have procedures, and those procedures are not always your enemy. Law enforcement confiscates. It also returns. Evidence gets documented. Lawyers get involved. Rules exist, and they often get followed — not always, not everywhere, not under every administration, but more often than the pure paranoia model assumes. The threat is real. The threat is also not absolute. The problem is that when you are standing in a crowd in a contested environment, you do not know which situation you are in.

That is the actual problem Clutch is built to solve. Not "am I being surveilled" with a yes or no answer. But: is the cellular environment around me behaving like normal infrastructure, or is it behaving like something else? Enough signal to make a better decision. Not certainty. Visibility.

What Cell-Site Simulators Actually Do

An IMSI catcher — a Stingray, a DRT box, a cell-site simulator — impersonates a legitimate cell tower. Your phone, following normal protocol, connects to whatever has the strongest signal. The device does not verify that the tower is legitimate. It never has. That trust model was baked into the cellular stack in an era when the idea of a portable fake tower was theoretical.

The simulator captures your IMSI (International Mobile Subscriber Identity) — the number that uniquely identifies your SIM. From there, depending on sophistication: location tracking, call interception, SMS capture, HTTPS downgrade if the software is current enough. The entry-level version is just the IMSI. The high-end version is a man-in-the-middle attack on your entire cellular layer.

The tell that betrays most deployments:

  • Forced technology downgrade. LTE to 3G to 2G. The simulator needs your device on an older protocol where encryption is weaker or absent. A5/3 to A5/1 to None. Your phone does not explain why it just dropped to EDGE in the middle of a city with full LTE coverage.
  • Signal strength anomalies. A legitimate tower kilometers away does not suddenly appear at strength that suggests it is standing next to you. A +25 dBm jump with no infrastructure change is not normal.
  • Timing advance zero. Timing advance is the cellular network's way of compensating for the distance between your device and the tower. Zero timing advance means the tower is right next to you. If there is no tower right next to you, that is information.
  • Tower ID irregularities. Cell IDs operate within known ranges for given areas. An ID that is out of range for your location, or that appears suddenly and disappears, is a pattern.
  • Unusual frequency behavior. Operating on non-standard frequencies or shifting frequency mid-session without a network-level explanation.

Here is how those three tells translate directly into detection logic — signal jump, encryption collapse, forced downgrade, each generating a typed threat with confidence score and evidence:

def _detect_imsi_catcher(self, measurement: CellularMeasurement) -> List[SecurityThreat]:
    threats = []

    # Signal jump: fake tower boosting to pull your device
    if len(self.measurement_history) > 1:
        prev = self.measurement_history[-2]
        signal_jump = measurement.signal_strength - prev.signal_strength

        if signal_jump > self.signal_jump_threshold:  # default: 20 dBm
            threats.append(SecurityThreat(
                threat_type="IMSI_CATCHER_SUSPECTED",
                severity="high",
                description=f"Sudden signal jump of {signal_jump} dBm",
                evidence={
                    "signal_jump": signal_jump,
                    "previous_strength": prev.signal_strength,
                    "current_strength": measurement.signal_strength,
                },
                confidence=0.7,
                mitigation_advice="Monitor for additional indicators. Consider disabling automatic cell selection."
            ))

    # Encryption gone: A5/3 → A5/1 → None — the silence before interception
    if measurement.encryption_status in ["None", "A5/0"]:
        threats.append(SecurityThreat(
            threat_type="ENCRYPTION_DOWNGRADE",
            severity="high",
            description="Encryption disabled or absent",
            evidence={"encryption_status": measurement.encryption_status},
            confidence=0.8,
            mitigation_advice="Avoid sensitive communications. Move and monitor."
        ))

    # Forced 2G: LTE was there five measurements ago. Now it isn't.
    if measurement.technology in ["2G", "GSM"]:
        recent_techs = [m.technology for m in list(self.measurement_history)[-5:]]
        if any(t in ["4G", "LTE", "5G"] for t in recent_techs):
            threats.append(SecurityThreat(
                threat_type="FORCED_TECHNOLOGY_DOWNGRADE",
                severity="medium",
                description=f"Forced downgrade to {measurement.technology}",
                evidence={"recent_technologies": recent_techs},
                confidence=0.6,
                mitigation_advice="Verify coverage issue or active IMSI catcher."
            ))

    return threats

Harris Corporation — the manufacturer of the original Stingray — spent years getting law enforcement agencies to sign NDAs as a condition of purchase. Police departments suppressed evidence in criminal cases rather than disclose that they had used the device. The Baltimore Sun, the ACLU, and EFF eventually cracked that open. The technology had been in field use for over a decade before the public picture became clear.

It is in widespread use by law enforcement, intelligence agencies, and in some countries, private actors. The deployment at protests specifically is documented — including the 2020 demonstrations in Washington, D.C., where researchers identified IMSI catcher signatures at multiple locations.

Red Team: How They Hide

A sophisticated IMSI catcher deployment tries to blend:

  • Signal strength normalized to plausible tower values — no obvious boost
  • Frequency matching the legitimate carrier in the area
  • Temporary deployment windows — bring it up, collect, bring it down before pattern analysis catches the anomaly
  • Multiple devices creating overlapping coverage to confuse correlation
  • No downgrade if the target is on a monitored whitelist and the operator wants passivity rather than intercept

What they cannot always hide: the physics. Timing advance anomalies under aggressive signal conditions. Cell ID behavior that does not match the infrastructure map. Correlated anomalies across multiple indicators at once, in the same time window, in a location where deployment is plausible.

No single indicator is proof. A pattern across indicators, in context, is signal.

Blue Team: What Clutch Gives You

Clutch monitors the cellular layer on iOS and macOS/Linux and watches for the patterns that betray cell-site simulator behavior.

The detection stack:

HACK LOVE BETRAY
COMING SOON

HACK LOVE BETRAY

Mobile-first arcade trench run through leverage, trace burn, and betrayal. The City moves first. You keep up or you get swallowed.

VIEW GAME FILE
  • Real CoreTelephony integration — actual cellular hardware data, not approximations
  • Signal pattern analysis — IsolationForest and DBSCAN anomaly detection on RSSI, timing advance, and technology layer
  • Downgrade alerts — notification when encryption weakens without a network-level explanation
  • Cell ID validation — flags tower IDs out of range for the geographic area
  • RF fingerprinting — protocol anomaly analysis at the cellular layer
  • Multi-device coordination — WebSocket server for sharing threat data across a team in real time

Each measurement runs through the full stack in sequence. The ML layer only fires after the rule-based detectors have had their pass:

def analyze_measurement(self, measurement: CellularMeasurement) -> List[SecurityThreat]:
    threats = []

    # Rule-based detection: fast, interpretable, no model required
    threats.extend(self._detect_imsi_catcher(measurement))
    threats.extend(self._detect_signal_anomalies(measurement))
    threats.extend(self._detect_location_anomalies(measurement))
    threats.extend(self._detect_encryption_anomalies(measurement))
    threats.extend(self._detect_tower_behavior_anomalies(measurement))

    # ML layer: IsolationForest + DBSCAN on top of the rule results
    if ML_AVAILABLE:
        threats.extend(self._ml_anomaly_detection(measurement))
        threats.extend(self._advanced_pattern_analysis(measurement))

    for threat in threats:
        self.security_threats.append(threat)
        self._handle_threat_notification(threat)

    return threats

The ML models are watching the same signals — but across fifty measurements at once, looking for behavioral outliers that no single rule would catch. Here is the feature vector it trains on:

# What IsolationForest actually sees per measurement
feature_row = [
    measurement.signal_strength,          # raw dBm
    measurement.signal_quality or 0,       # quality score
    measurement.timing_advance or 0,       # proximity indicator
    self._technology_to_score(measurement.technology),    # LTE=4, 3G=3, 2G=1
    self._encryption_to_score(measurement.encryption_status),  # A5/3=3, A5/1=2, None=0
    time_diff,      # seconds since last measurement
    signal_diff,    # dBm change since last measurement
]
# IsolationForest flags anything in the top 10% most anomalous
# DBSCAN clusters tower behavior — outlier ratio > 20% triggers alert

The physics that betrays a fake tower shows up in that vector: timing advance near zero, signal_diff spiking, encryption score dropping to zero, technology score falling from 4 to 1 — all in the same window. One indicator is noise. A pattern across all seven is not.

What you see when it fires:

IMSI CATCHER DETECTED

Threat Type: IMSI_CATCHER_SUSPECTED
Severity: HIGH
Confidence: 0.85

Evidence:
- Signal jump: +28 dBm (threshold: 25 dBm)
- Timing advance: 0 (suspicious proximity)
- Encryption: Downgraded A5/3 → None
- Frequency: 1950 MHz (non-standard)
- Cell ID: Out of valid range

Mitigation:
- Avoid sensitive communications immediately
- Move location if tactically safe
- Enable airplane mode if appropriate
- Monitor for pattern consistency

The mitigation suggestions are defaults. The tool is designed to be adjustable — threat models vary, and a journalist covering a protest in New York has a different operational picture than a fixer moving through a warzone. The sensitivity thresholds are configurable. The alert behavior is configurable. The system does not decide what you do. It gives you more information than you had before and lets you decide.

That is the whole design philosophy.

Who This Is For

The "leave your phone at home" crowd is not wrong about the threat. They are wrong about the operational reality for a lot of the people who face it.

A journalist covering a front line has sources on that phone. Navigation. Emergency contacts. The documentation of the day. Leaving it at the hotel is sometimes the right call. It is not always available as a call.

An activist organizing in a city with an active surveillance program needs to communicate. Operational silence is not always tactically superior to operational awareness.

A security team protecting an executive in a contested environment needs to know whether the cellular layer in that meeting room is clean.

A researcher needs to know whether the conference they are attending has been turned into a collection environment.

The threat is not uniform. The response should not be uniform either. A tool that gives you the cellular picture and lets you calibrate your response is more useful than advice that assumes you can afford to go dark.

Open Source Because It Has To Be

Surveillance detection software that asks for your trust without showing you what it is doing has a structural problem. The thing it is supposed to protect you from operates through opacity. A defensive tool should not imitate that.

Clutch is open source. The detection algorithms are readable. The data handling is auditable. You can verify that the threat database is local, that remote sharing is opt-in and configurable, that nothing leaves the device unless you configure it to.

If the tool does not fit your threat model, fork it and build what does.

github.com/ghostintheprompt/clutch


GhostInThePrompt.com // The tower decides what your phone trusts. Clutch gives you a vote.