Edge AI Security Atlas

Threat Library deep dive for backend isolation, VLAN boundaries, and gateway-only accelerator access.

A5 / Software attack / High

Direct Backend Exposure

Jetson Orin Nano or Zynq-7020 backend services become reachable from the client side instead of being reachable only through the Raspberry Pi gateway. The immediate risk is gateway-control bypass: authentication, rate limits, request shaping, audit logging, and dispatch policy no longer mediate access to the accelerators.

Where It Appears In The Edge AI Architecture

A5 sits at the boundary between public client access and private accelerator services.

Client / public side Pi gateway / trust boundary Private LAN2 accelerators Client laptop 192.168.10.100 Switch Raspberry Pi LAN1 :8000 LAN2 gateway FLAT LAN Jetson Orin :8001 inference Zynq-7020 :8002 FPGA REST client reaches backend ports directly
Backends bypass the Pi Client-side traffic can reach Jetson :8001 or Zynq :8002 directly, so gateway authentication, throttling, and logging are skipped.

Threat Model

The attacker is on the owned client side of the lab and can attempt to reach backend service addresses that should be private.

Attacker capability

The attacker controls a client device on the public or lab client VLAN, such as the MacBook or ThinkPad. They can generate synthetic validation traffic inside the owned lab, but the safe lab below uses a policy simulator instead of live probing.

Trust assumption being tested

Jetson and Zynq services are private accelerators. They should accept inference work only from the Raspberry Pi LAN2 interface, not from client hosts, guest networks, mirrored switch ports, or accidental flat-LAN paths.

Assets at risk

Backend model oracle access, accelerator availability, request auditability, benchmark isolation, Jetson service metadata, Zynq PS REST shim behavior, and any controls enforced only at the Pi gateway.

Out of scope

No third-party scanning, no brute-force discovery, no exploit payloads, and no instructions to attack external networks. Validation should be limited to owned, isolated lab addresses or the toy simulator provided here.

Attack Intuition

Private backend services are safe only if the network actually makes them private.

The Raspberry Pi gateway is supposed to be the choke point. It authenticates callers, enforces rate limits, applies payload limits, chooses Jetson versus Zynq, logs enough telemetry, and hides private backend details. If a client can connect directly to 192.168.30.10:8001 or 192.168.30.20:8002, the logical architecture on the diagram no longer matches the real packet path.

A5 is not about breaking a backend service. It is about discovering that the backend service was accidentally placed in the wrong exposure class: bound to all interfaces, bridged through the switch, reachable through a misconfigured VLAN, exposed through a host route, or published by a convenience port forward left over from development.

Safe framing: the demonstration below is a deterministic local simulator. It models reachability decisions from configuration data and synthetic packets; it does not scan any real network or contact Jetson, Zynq, or third-party systems.

Technical Explanation

A5 happens when backend reachability is broader than the intended trust boundary.

Service binding

A backend that listens on 0.0.0.0 or the wrong interface may be reachable from any routed segment. D4 prefers binding Jetson and Zynq services only to LAN2 addresses and rejecting non-Pi sources at the host firewall.

VLAN segmentation

The switch should keep client LAN and private LAN2 separate. A trunk, access-port mistake, bridge interface, or temporary test cable can flatten the topology and make the private zone reachable.

Gateway bypass

When direct backend access works, D1, D2, D3, D5, D6, and D8 may be bypassed because those controls live at the Pi path. Defense must exist both at network segmentation and backend host policy.

The clean design is defense in depth: switch VLAN rules prevent the path, Pi routing controls define the only intended route, backend host firewalls allow only the Pi LAN2 address, and backend services bind only to private interfaces. The gateway then becomes the deliberate policy point rather than a hopeful convention.

Mathematical Formulation

Model A5 as a reachability and policy-composition problem.

Hosts H = {client, pi_lan1, pi_lan2, jetson, zynq} Services S = {(jetson, 8001), (zynq, 8002)} Trusted source for S: pi_lan2 only Reachability predicate: R(src, dst, port) = Route(src, dst) AND VlanAllows(src, dst) AND HostFirewallAllows(src, dst, port) AND ServiceBound(dst, port) D4 objective: For every client c on public/client VLAN: R(c, jetson, 8001) = false R(c, zynq, 8002) = false Gateway objective: R(pi_lan2, jetson, 8001) = true R(pi_lan2, zynq, 8002) = true Exposure score for a configuration C: exposure(C) = count of forbidden tuples where R(tuple) = true A5 exists when exposure(C) > 0.

This framing makes A5 measurable. You can test a configuration by enumerating allowed and forbidden tuples, then proving that the forbidden set is empty while the required gateway paths remain available.

Step-By-Step Safe Lab Demonstration

The lab evaluates synthetic topology policies instead of probing real ports.

  1. Save the Python code from the next section as a5_backend_exposure_policy_lab.py.
  2. Run python3 a5_backend_exposure_policy_lab.py --mode exposed to model a flat or misbound network.
  3. Run python3 a5_backend_exposure_policy_lab.py --mode isolated to model D4 segmentation and backend allow-listing.
  4. Compare forbidden_allowed, required_allowed, and exposure_score.
  5. Translate the same test table to your real lab documentation before any live validation. If you do live validation, keep it to owned addresses and record only defensive allow/drop evidence.

Interactive toy replay

Replay expected policy outcomes inside the page. It is display-only and never opens a socket.

ready: no policy simulation replayed yet

Full Code For A Local Simulated Lab

This code computes allow/drop decisions for synthetic packets. It does not scan, connect, sniff, or attack anything.

a5_backend_exposure_policy_lab.py
#!/usr/bin/env python3
"""
A5 local-only simulator: direct backend exposure.

This program evaluates synthetic reachability decisions for an owned Edge AI
lab topology. It does not open sockets, scan ports, sniff traffic, or contact
Jetson/Zynq/Pi devices. Use it to reason about D4 policy before any real lab
validation.
"""

import argparse
from dataclasses import dataclass
from typing import Dict, List, Tuple


@dataclass(frozen=True)
class Host:
    name: str
    vlan: str
    ip: str


@dataclass(frozen=True)
class Service:
    host: str
    port: int
    bind: str
    allowed_sources: Tuple[str, ...]


HOSTS: Dict[str, Host] = {
    "client": Host("client", "client_vlan", "192.168.10.100"),
    "pi_lan1": Host("pi_lan1", "client_vlan", "192.168.10.2"),
    "pi_lan2": Host("pi_lan2", "private_lan2", "192.168.30.1"),
    "jetson": Host("jetson", "private_lan2", "192.168.30.10"),
    "zynq": Host("zynq", "private_lan2", "192.168.30.20"),
}

REQUIRED = [("pi_lan2", "jetson", 8001), ("pi_lan2", "zynq", 8002)]
FORBIDDEN = [("client", "jetson", 8001), ("client", "zynq", 8002)]


def build_services(mode: str) -> Dict[Tuple[str, int], Service]:
    if mode == "exposed":
        return {
            ("jetson", 8001): Service("jetson", 8001, "0.0.0.0", ("client", "pi_lan2")),
            ("zynq", 8002): Service("zynq", 8002, "0.0.0.0", ("client", "pi_lan2")),
        }
    return {
        ("jetson", 8001): Service("jetson", 8001, "192.168.30.10", ("pi_lan2",)),
        ("zynq", 8002): Service("zynq", 8002, "192.168.30.20", ("pi_lan2",)),
    }


def vlan_allows(src: str, dst: str, mode: str) -> bool:
    if src == "pi_lan2" and HOSTS[dst].vlan == "private_lan2":
        return True
    if mode == "exposed":
        return True
    return HOSTS[src].vlan == HOSTS[dst].vlan


def route_exists(src: str, dst: str, mode: str) -> bool:
    if mode == "exposed":
        return True
    return src == "pi_lan2" and HOSTS[dst].vlan == "private_lan2"


def service_bound(service: Service, dst: str) -> bool:
    return service.bind == "0.0.0.0" or service.bind == HOSTS[dst].ip


def firewall_allows(service: Service, src: str) -> bool:
    return src in service.allowed_sources


def reachability(src: str, dst: str, port: int, mode: str) -> Tuple[bool, List[str]]:
    services = build_services(mode)
    service = services.get((dst, port))
    reasons = []
    if not service:
        return False, ["no_service"]
    checks = {
        "route": route_exists(src, dst, mode),
        "vlan": vlan_allows(src, dst, mode),
        "service_bind": service_bound(service, dst),
        "host_firewall": firewall_allows(service, src),
    }
    for name, ok in checks.items():
        if not ok:
            reasons.append("blocked_by_" + name)
    return all(checks.values()), reasons or ["allowed"]


def evaluate(mode: str) -> int:
    exposure_score = 0
    print("mode=%s" % mode)
    for src, dst, port in FORBIDDEN:
        allowed, reasons = reachability(src, dst, port, mode)
        if allowed:
            exposure_score += 1
        print(
            "tuple=forbidden src=%s dst=%s port=%s decision=%s reasons=%s"
            % (src, dst, port, "ALLOW" if allowed else "DROP", ",".join(reasons))
        )
    for src, dst, port in REQUIRED:
        allowed, reasons = reachability(src, dst, port, mode)
        print(
            "tuple=required src=%s dst=%s port=%s decision=%s reasons=%s"
            % (src, dst, port, "ALLOW" if allowed else "DROP", ",".join(reasons))
        )
    print("exposure_score=%s" % exposure_score)
    return exposure_score


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--mode", choices=["exposed", "isolated"], default="exposed")
    args = parser.parse_args()
    score = evaluate(args.mode)
    if args.mode == "isolated" and score == 0:
        print("result=pass d4_private_backend_subnet_enforced")
    elif score > 0:
        print("result=fail direct_backend_exposure_present")
    else:
        print("result=check_required_paths")


if __name__ == "__main__":
    main()
local simulator commands
# Vulnerable model: client can reach backend services directly in the synthetic policy.
python3 a5_backend_exposure_policy_lab.py --mode exposed

# Secure model: only Pi LAN2 can reach Jetson :8001 and Zynq :8002.
python3 a5_backend_exposure_policy_lab.py --mode isolated

# Expected secure result:
# tuple=forbidden src=client dst=jetson port=8001 decision=DROP ...
# tuple=forbidden src=client dst=zynq port=8002 decision=DROP ...
# result=pass d4_private_backend_subnet_enforced

Practical Example For Your GPU + Pi + Jetson + Zynq Setup

A5 is the question: can the MacBook reach the accelerators without passing through the Pi?

Intended topology

The MacBook or ThinkPad sits on the client side. It talks to the Pi gateway on LAN1. The Pi talks to Jetson and Zynq on LAN2. The switch/VLAN/private subnet design should make Jetson and Zynq invisible from the client path except through gateway-mediated inference.

client VLANPi gatewayprivate LAN2

A5 failure mode

A development shortcut exposes Jetson :8001 or Zynq :8002 to the client network. That might come from flat VLAN membership, service binding to all interfaces, host firewall gaps, a temporary bridge, or a switch port configured as trunk instead of access.

gateway bypassbackend oracleD4 required

For your portal experiments, treat D4 as a measurable prerequisite. Before collecting inference latency, throughput, extraction-resistance, or fault-injection results, log the policy state that proves the Pi is the only source allowed to reach the backend services.

Observable Signals Or Logs

A5 should be visible as allow/drop evidence at the switch, Pi, and backend host layers.

LayerRisk signalHealthy D4 signal
Switch / VLANClient port and backend port share the same reachable segment or trunk behavior unexpectedly allows backend traffic.Client VLAN and LAN2 are separated; backend ports are access ports in private LAN2 only.
Pi gatewayBackend receives work not reflected in Pi request logs, meaning the gateway was bypassed.Every backend request has a corresponding Pi log entry with user, route, backend, and policy decision.
Jetson hostAccess logs show client-side source addresses instead of Pi LAN2 source.Only Pi LAN2 source appears for inference service connections.
Zynq PSREST shim sees client-side addresses or unmediated requests to FPGA control endpoints.PS firewall allows Pi LAN2 only; unexpected source addresses are dropped before application logic.
Research logsBenchmark results mix gateway-mediated and direct-backend paths.Each run records topology hash, VLAN profile, firewall policy version, and backend source evidence.

Impact Analysis

Direct backend exposure converts one controlled API into multiple uncontrolled APIs.

Confidentiality

Direct access can expose prediction outputs, confidence patterns, service banners, health metadata, backend timing, and model-oracle behavior without gateway identity binding.

Integrity

If backend control or management endpoints are reachable, a caller may bypass gateway-side object checks or dispatch policy. Even read-only inference bypass can compromise experiment integrity by mixing paths.

Availability

Jetson and Zynq services may be easier to overload directly because D2 rate limits, payload caps, and D8 timeout policy often live at the Pi boundary.

Mapping To CIA, STRIDE, PASTA, And MITRE ATLAS

A5 is a classic trust-boundary failure with AI-specific oracle and accelerator consequences.

FrameworkA5 mappingResearch interpretation
CIAConfidentiality, Integrity, and AvailabilityThe attacker bypasses gateway controls to reach model-serving backends and accelerator resources directly.
STRIDEInformation Disclosure, Tampering, Denial of Service, Elevation of Privilege, RepudiationThe path skips identity, audit, authorization, and rate-control layers normally enforced by the Pi.
PASTAStage 3 decomposition, Stage 4 threat analysis, Stage 5 vulnerability analysis, Stage 6 attack modelingModel trust zones, data flows, and backend service exposure as first-class security assumptions.
MITRE ATLASRelevant to model access, discovery, collection, and AI service abuse patterns where an adversary reaches the serving endpoint outside intended controls.A5 creates the unmediated model-oracle path that later attacks such as extraction, timing analysis, or backend-specific abuse can depend on.
MITRE ATT&CKRelated to network service discovery, exposed services, lateral movement pathways, and endpoint access control gaps.Traditional network exposure becomes AI-specific because the reachable service is an accelerator-backed inference backend.

Defense Mapping To Existing D1-D11 Controls

D4 is primary, but A5 shows why gateway and backend controls should reinforce each other.

ControlRole against A5Validation
D4 Private Backend SubnetPrimary control. Put Jetson and Zynq on LAN2, bind services to private interfaces, enforce switch VLANs, and allow only Pi LAN2 as source.Forbidden client-to-backend tuples drop; required Pi-to-backend tuples pass.
D1 JWT Auth + Object ChecksProtects the intended public path but can be bypassed if A5 exists. Backend services should still have minimal internal auth for defense in depth.Direct backend calls cannot produce useful work without gateway identity or internal service credential.
D2 Rate Limit + Body CapLimits public gateway abuse but does not help if clients can skip the gateway. Backend host policy should provide secondary connection limits.No backend request is observed without a matching Pi rate-limit decision.
D3 TLS EverywherePrevents cleartext on allowed paths and supports mTLS Pi-to-backend authentication.Backends accept mTLS client identity from Pi only.
D5 Query Anomaly DetectionDetects model-oracle abuse only if telemetry includes all backend requests. A5 creates blind spots.Backend logs and Pi logs reconcile one-to-one.
D6 Sanitized LoggingProvides evidence of gateway bypass by comparing backend source addresses and Pi request IDs.Unexpected client source is logged as policy violation without storing sensitive payloads.
D8 Backend Timeout / Circuit BreakerProtects gateway-mediated backend calls. Backend-local timeouts and process supervisors should also exist.Direct overload paths are unavailable; gateway timeout metrics remain authoritative.

Research Notes: What To Measure Experimentally

A5 can be measured with reachability matrices and log reconciliation, not dramatic traffic.

Reachability matrix

Enumerate source, destination, port, route, VLAN, firewall, and expected decision. The core metric is forbidden paths allowed versus required paths allowed.

Control-plane drift

Hash switch config, Pi firewall rules, backend service binding, and backend firewall state. Track whether exposure changes between experiments.

Log reconciliation

For every backend request, require a matching Pi gateway request ID. A mismatch indicates direct backend access, missing logging, or out-of-band maintenance traffic.

Benchmark contamination

Compare latency and throughput distributions for gateway-mediated paths versus direct backend paths in a safe, owned lab. Keep them separate in research results.

Key Takeaways

A private backend is a property you continuously verify, not a label on a diagram.

  • A5 exists when Jetson or Zynq backend ports are reachable from the client side instead of only from Pi LAN2.
  • The Pi gateway controls are meaningful only if traffic cannot bypass the Pi.
  • D4 should be validated at multiple layers: service bind address, host firewall, Pi routing, switch VLANs, and log reconciliation.
  • For research, record topology and reachability evidence beside every benchmark or security experiment.