HOWTO: Locking LG out of a rooted webOS TV
So you have an LG TV and you want to use the “smart” features i.e. plug it into ethernet?
Our highest and best recommendation is to run the script to programmatically reject all agreements/EULAs and then just use it as a dumb display, but if you want to live dangerously.. this is a sort of mini how-to wiki.
This has also only been tested on the one target, but should be pretty readily adaptable to other models assuming something doesn’t work. If it gets complicated, I’m going to put the scripts attached here into a git repo.
Target: OLED65G5WUA, webOS 10.2.1 (starfish, build ponytail-paparoa), kernel
5.4.268-329.ptl4tv.2, LG1214 SoC, Homebrew Channel running (org.webosbrew.hbchannel.service), dropbear SSH :22 + telnetd :23,
dev mode enabled.
Audience: technically-savvy user with root SSH access to the TV.
The absolute best starting place is the Homebrew community for LG
https://www.webosbrew.org/ This is all old hat for them; been there; done that. Ironically, because I feel we cannot trust LG rooting your TV is the best way to ensure that you own the glass, not them.
Massive props, shout-out and thanks to the webOS Homebrew community. Hello and welcome!
Companion scripts: # scripts . Every script is idempotent,
POSIX /bin/sh, has a --dry-run mode, backs up before overwriting, and never
touches /var/lib/webosbrew/startup.sh or jumpstart.sh.
[!IMPORTANT]
Nothing in this document is applied automatically. You run these commands on your own rooted TV at your own risk. A factory reset wipes root, the Homebrew Channel, and every change below (This is your escape hatch at any time.)
The threat model (why layered)
LG’s TV firmware phones home through several independent channels, and no single
mechanism stops all of them:
| Channel | Process | Endpoint |
|---|---|---|
| OS updates | /usr/sbin/update |
snu/su/su-ssl/nsu.lge.com + hardcoded IP 156.147.69.32:8080 |
| Telemetry | /usr/sbin/sdx |
nextlgsdp.com, *.lgtvcommon.com, … (live: 54.186.247.229:443) |
| ACR | /usr/sbin/acr2 |
(configured, currently inert) |
| Ads | /usr/sbin/admanager |
info.lgsmartad.com (~every 60 s) |
| ThinQ/IoT | iot-client, pushclient |
*.lgtviot.com, *.lgthinq.com, AWS IoT MQTT |
| LLM/AI | com.webos.app.aiplatform |
ngfts.lge.com family |
| Crash/analytics | uploadd, rdxd |
rdx2.nextlgsdp.com, rdl.lgtvcommon.com |
| Consents | eula-service |
/var/luna/preferences/eula (accepted: Marketing, Privacy, Voice, ACR, IBA ads) |
Key platform facts that shape the design (all verified on this TV):
/etc/hostsis on a read-only overlay (You cannot edit it in place.) The
only way to change it is a bind-mount of a modified copy (this is exactly
what Homebrew Channel’s ownstartup.shdoes).iptablesexists but there are no netfilter kernel modules So firewall
rules fail. Null routes are kernel state and vanish on reboot. Neither is a
viable on-TV mechanism.- The persistence mechanism is
/var/lib/webosbrew/init.d/*So executable
scripts (no dots in the filename) run as root every boot by Homebrew Channel’s
startup.shviarun-parts. This survives reboots (not factory reset). - The only thing that survives a factory reset is blocking done outside
the TV: at the router.
Hence the layered design: router layer (survives everything, catches
hardcoded-IP fallbacks) + on-TV layers (official HBChannel blockers + custom
init.d hosts bind-mount + consent decline).
Layer 0: Preflight
Goal: confirm the TV is in the expected state and take backups before changing
anything.
0.1 Confirm root + Homebrew Channel
ssh root@(ip of your TV)
# expect: root@LGwebOSTV, alpine
ls -la /var/lib/webosbrew/
# expect: startup.sh, sshd/, and an (empty) init.d/
ls /media/developer/apps/usr/palm/services/ | grep hbchannel
# expect: org.webosbrew.hbchannel.service
RATIONALE: every later layer depends on the Homebrew Channel’s startup.sh
running our init.d hooks as root at boot. If the TV is not rooted or HBChannel
is not running, init.d never executes and Layers 2–5 silently do nothing. The
empty init.d/ on this TV is a clean hook point so there isn’t anything to conflict with.
0.2 Back up the files we will modify
mkdir -p /tmp/lg-lockout-backup
cp -a /etc/hosts /tmp/lg-lockout-backup/hosts
cp -a /var/luna/preferences/eula /tmp/lg-lockout-backup/eula
cp -a /var/luna/preferences/option /tmp/lg-lockout-backup/option
cp -a /var/luna/preferences/general /tmp/lg-lockout-backup/general
cp -a /mnt/lg/cmn_data/sdp/sdx/server_addr_version.conf /tmp/lg-lockout-backup/
RATIONALE: the consent files are JSON and the eula file is the one place a mistake is hard to undo by eye. A timestamped copy costs nothing and gives you a clean restore path. (The scripts also make their own .bak.* copies before every overwrite. The aim is best-practices and a little bit paranoia if you come back here to ask for help. )
0.3 Know the escape hatch
Factory reset (Settings > General >Reset, or the physical reset procedure)
wipes /var and /media: root, Homebrew Channel, dev mode, and every lockout
change are gone; the TV returns to stock LG firmware with all consents accepted.
RATIONALE: documenting this up front removes the fear factor; nothing you do
here should be irreversible. It also sets the expectation that the durable layer is
the router one (Layer 1), because only that one survives a reset.
Layer 1: Router / DHCP DNS blocking (survives everything)
Goal: make the TV unable to resolve or reach LG endpoints at the network
level, independent of anything on the TV.
1.1 Block LG domains in your DNS resolver (Pi-hole / dnsmasq)
# dnsmasq.conf (or Pi-hole Local DNS → DNS records, or AdGuard Home)
address=/nextlgsdp.com/0.0.0.0
address=/lgtvcommon.com/0.0.0.0
address=/lgsmartad.com/0.0.0.0
address=/lgtviot.com/0.0.0.0
address=/lgthinq.com/0.0.0.0
address=/snu.lge.com/0.0.0.0
address=/su.lge.com/0.0.0.0
address=/su-ssl.lge.com/0.0.0.0
address=/nsu.lge.com/0.0.0.0
address=/snu-dev.lge.com/0.0.0.0
address=/su-dev.lge.com/0.0.0.0
address=/ngfts.lge.com/0.0.0.0
# address=/lgsmartweb.com/0.0.0.0 # breaks voice search
# optional tradeoffs (see #BLOCKLIST section):
# address=/lgtvsdp.com/0.0.0.0 # breaks Content Store
# address=/lgappstv.com/0.0.0.0 # breaks Content Store
The TV’s resolver is the local connmand proxy on 127.0.0.1:53, which forwards
to your DHCP-provided upstream DNS (on this network: 10.200.0.3/.4/.5).
Blocking at the upstream resolver covers the TV with zero TV-side changes.
RATIONALE: this is the most robust layer because it’s outside the TV, it’ll survive every TV reboot, every TV factory reset, and even a re-root. It is the only layer that can catch
the hardcoded OTA fallback IP (see 1.3) and the only layer that stops the boot-time update check, which runs before startup.sh and therefore before any hosts bind-mount exists. If you skip this layer, a factory reset silently re-arms all LG phone-home with no on-TV defense left. This should also stop the forced “hey we changed the EULA don’t not not don’t do anything to confirm changes” they have lately started doing with the forced EULA popups…
1.2 Block outbound DNS to anything but your resolver
# firewall (OpenWrt / pfSense / your router):
# reject outbound :53 from the TV's subnet to any IP except your resolver
RATIONALE: some webOS firmwares bypass DHCP DNS and hardcode 8.8.8.8 (or
similar) as the resolver. If the TV can reach a public resolver, Layer 1.1 is
trivially bypassed and the TV resolves LG domains again. Blocking outbound :53
forces the TV to use only your resolver.
1.3 Block LG’s hardcoded IPs at the firewall
# reject outbound from the TV to:
# 156.147.69.32:8080 (hardcoded OTA fallback on the TV from Steve's video; domain blocks MISS this)
# 54.186.247.229:443 (observed live sdx telemetry endpoint, AWS)
RATIONALE: /usr/sbin/update contains a hardcoded IP fallback
(http://156.147.69.32:8080/CheckSWAutoUpdate.laf) used when DNS fails, which is exactly
the situation our DNS blocks create. Hosts files and DNS can never block an IP;
only a firewall can. 54.186.247.229 was the live sdx telemetry destination at
recon time; AWS endpoints can move, so this is something we should make a note to watch in the future.
Do you have Pi-hole? If you have pi-hole on your network you can watch a lot of this DNS traffic via pi-hole. But it doesn’t work for these hard-coded fallbacks.
Layer 2: Built-in Homebrew Channel blockers
Goal: enable the official, zero-maintenance blockers that ship with Homebrew
Channel.
2.1 Enable the block-updates flag
ssh root@(your tv ip)
touch /var/luna/preferences/webosbrew_block_updates
On every boot, startup.sh then:
- bind-mounts a hosts file with
snu.lge.com su-dev.lge.com su.lge.com su-ssl.lge.com
pointed at127.0.0.1+::1(the core OTA domains), and - read-only bind-mounts a stub over
/tmp/rdxd,/tmp/uploadd,
/var/spool/rdxd,/var/spool/uploadd/{pending,uploaded}the telemetry
spool directories souploadd/rdxdcannot write crash/analytics data.
RATIONALE: this is the official mechanism maintained upstream by the
Homebrew Channel project, zero maintenance, and it exercises the exact
bind-mount technique our custom Layer 3 script reuses. Enable it first because
it is the most likely to keep working across Homebrew Channel updates. It only
covers the 4 core OTA domains, which is why Layer 3 adds even more stuff.
Layer 3 — Custom init.d hosts blocklist (10-block-lg-telemetry)
Goal: bind-mount a comprehensive hosts blocklist on every boot.
3.1 Install the script
# from your machine:
scp -r lg-lockout root@(your tv IP):/tmp/
ssh root@(your tv IP)
mkdir -p /var/lib/webosbrew/init.d
cp /tmp/lg-lockout/scripts/10-block-lg-telemetry /var/lib/webosbrew/init.d/
chmod 755 /var/lib/webosbrew/init.d/10-block-lg-telemetry
RATIONALE: run-parts executes every executable file in init.d/ so we name our file 10-block-lg-telemetry (the 10- prefix also orders it before any later hooks). chmod 755 is required or run-parts skips it. The script itself:
- copies
/etc/hoststo/tmp, appends0.0.0.0 <domain>+::1 <domain>for
every domain in its block list, thenmount --binds the copy over/etc/hosts
— the only way to change hosts on the RO overlay; - is idempotent (re-running refreshes the file, never duplicates entries);
- self-heals on reboot (the bind mount is not persistent; a fresh copy is made
every boot); - has an opt-out flag (
/var/luna/preferences/webosbrew_block_updates_extra_off)
so you can drop the long-tail list without uninstalling.
RATIONALE (why bind-mount and not echo >> /etc/hosts): /etc/hosts is on
the read-only overlay because direct writes fail or are silently lost. The bind-mount
is the verified technique used by Homebrew Channel itself. Why not iptables or
null routes? iptables has no netfilter kernel modules on this TV (rules fail),
and null routes are kernel state wiped on reboot. Hosts bind-mount is the only
working on-TV mechanism.
3.2 Apply now (no reboot required)
sh /var/lib/webosbrew/init.d/10-block-lg-telemetry
cat /etc/hosts # confirm the block entries are visible
RATIONALE: the init.d hook only fires at next boot. Running it once by hand
applies the block immediately, so you can verify before rebooting.
3.3 What the block list covers
Full list with sources in BLOCKLIST Section. Summary: OTA (snu/su/su-ssl/nsu/ snu-dev/su-dev.lge.com), SDX telemetry (nextlgsdp.com family + all
*.lgtvcommon.com services + lggalleryplus.com + tv.wiselg.com), ads
(lgsmartad.com), ThinQ/IoT (*.lgtviot.com, *.lgthinq.com), LLM/AI
(ngfts.lge.com family), crash/analytics (rdx2.nextlgsdp.com,
rdl.lgtvcommon.com). Content Store (lgtvsdp.com, lgappstv.com) and voice
search (lgsmartweb.com) are commented out which are opt-in tradeoffs.
RATIONALE: every domain in the list was observed live on this TV (from the
sdx server_addr_version.conf map, binary strings, and live egress) or is
sourced from the community blocklists cited in the BLOCKLIST Section. Keeping the
tradeoff domains commented out means the default install never breaks Content
Store or voice search without an explicit choice. You should block the voice search, though.
Layer 4: Decline all LG ToS / consents (decline-tos.sh)
Goal: programmatically decline every LG consent at the source, so LG’s
services have no permission to collect.
4.1 Run the decline script
ssh [email protected]
sh /var/lib/webosbrew/lg-lockout/decline-tos.sh # after install.sh
# or, to preview first:
sh /var/lib/webosbrew/lg-lockout/decline-tos.sh --dry-run
What it does:
/var/luna/preferences/eulaThis sets everyeulaStatus.*Allowedkey to
false(false = declined) and every per-documentacceptedflag in
eulaInfo/eulaInfoNetworktofalse, marking themupdatedso the UI
re-reads them. On this TV that declines the currently-accepted S_MKT
Marketing, S_PRG Privacy, S_VNG Voice, S_ADG ACR&Viewing, S_TAG IBA ads./var/luna/preferences/optionThis setsvoiceAllowed=false,
voice2Allowed=false,watchedListCollection=off,usageCare=false,
dbgLogUpload=false,faultLogUpload=false,thirdPartyCookie=off./var/luna/preferences/generalThis setsaiNudge=off,screenSaverAd=off,
homePromotion=off,launchEulaByHome=false.- ACR opt-out marker This creates
/mnt/lg/cmn_data/acr/data/eula_disallowed_rebootedand removes
eula_allowed. - Restarts
eula-service(andacr2if present) so the daemons re-read the
files.
RATIONALE: this is the “we own the glass” consent grab declined at the
source. LG’s eula-service daemon exposes no public accept/decline API —
only start/requestEulaDownload/getEulaDownloadStatus/cancelEulaDownload/ resetEula Soooo… with root we write the state files directly. Declining at the
source matters because several services key off these flags independently of
network blocking: ACR (acr.xml is ACR_On=true but the consent gate and the
opt-out marker are what actually stop it), voice data collection, and the
diagnostic/usage uploads. If you only block the network, LG’s services still
believe they have consent; declining the consent removes the authorization too. NOTE: We have observed some “interesting stuff” with how this has changed across webOS versions. More on that may appear in a future video; this was against webOS 25.
[!NOTE]
eulaStatuswrite shape is high-confidence from the live file; thesetSystemSettingsLuna command (luna://com.webos.settingsservice/ setSystemSettings, categoryoption) is a documented alternative but the eula write shape is medium-confidence and the script backs up first for exactly this reason. There is probably no need to touch configd feature flagstv.conti.supportAcr/supportViewingInfoCollectionsince those seem to gate features, not consent. Significant reverse-engineering was required here and I feel LG may be deliberately obfuscating how it works from the end-user.
Layer 5: App-update gate bypass (clear-app-update-gate.sh, optional)
Goal: stop the Content Store’s “update available” nag without blocking the
Content Store itself.
5.1 Run the clear script
ssh root@(your TV IP)
sh /var/lib/webosbrew/lg-lockout/clear-app-update-gate.sh
It moves aside (with a .bak.* backup) the app store’s cached update state:
/mnt/lg/cmn_data/var/palm/data/com.webos.appInstallService/updateInfo
/mnt/lg/cmn_data/var/palm/data/com.webos.appInstallService/updateDependencyInfo
and leaves empty replacements, so the store sees “no pending updates”.
RATIONALE: adapted from dr0dr1dr2dr3/lgappupdateblocker, which blocks the
app-update gate via 172× 0.0.0.0 *.lgtvsdp.com hosts entries plus the
updateInfo wipe. We deliberately do not copy its hosts trick (it writes
/etc/hosts directly, which fails on the RO overlay; our Layer 3 covers hosts
via bind-mount) and we also wipe updateDependencyInfo, which the original
misses. This layer is optional: if you don’t care about app-update popups,
skip it.
[!WARNING]
updateInfocan be re-created by the app store after a reboot (upstream issue #2). The durable fix is the hosts/DNS layers stopping the store from reachinglgtvsdp.comin the first place but that breaks the Content Store (see caveats). This script is the no-tradeoff middle ground; run it after boot if you want it automatic.
Layer 6: Verification
Goal: confirm every layer is actually in place.
6.1 Run the verifier
ssh root@(your TV ip)
sh /var/lib/webosbrew/lg-lockout/verify-lockout.sh
It checks, and reports PASS/FAIL per item:
- hosts Check every expected block domain present; hosts is a bind mount.
- processes Check whether
sdx/uploadd/rdxd/admanagerare running (they
may still run but fail to phone home — that’s the goal) . - consents Check
networkAllowed,acrAllowed,voiceAllowedallfalsein
eula; option keys declined; ACR opt-out marker present. - egress Check
netstatscan for established/close-wait connections to LG
domains. - resolver Check resolv.conf points at the local connman proxy (so upstream
blocking is what matters). - app-update gate Check
updateInfoabsent or empty.
6.2 Manual spot-checks
# hosts block active?
cat /etc/hosts | grep -c '^0\.0\.0\.0' # expect ~50+
# can the TV still resolve LG domains? (should FAIL)
getent hosts snu.lge.com || echo "BLOCKED"
# consent state?
grep -E 'networkAllowed|acrAllowed|voiceAllowed' /var/luna/preferences/eula
# live egress (should show nothing to LG)
netstat -tn | grep -E ':(443|80|5100)' | grep -E 'lge\.com|lgsdp|lgsmartad|lgappstv|lgtviot|lgtvcommon|lgthinq|nextlgsdp|wiselg'
RATIONALE: a lockout you can’t verify is a lockout you can’t trust. The
failure modes are silent (services that keep running but fail quietly, hosts
mounts that didn’t take, consents that got re-accepted by a UI prompt). The
verifier turns “is it working?” into a 30-second checklist. The screenshot note:
capture the verifier output for your records.
What survives reboot vs factory reset
| Layer | Survives reboot | Survives factory reset |
|---|---|---|
| 1 Router DNS + firewall | ||
| 2 HBChannel built-in blockers | ||
| 3 init.d hosts bind-mount | ||
| 4 Consent decline | ||
| 5 App-update gate wipe | ||
| Root + Homebrew Channel |
Caveats
- Content Store tradeoff.
lgtvsdp.com+lgappstv.comare needed for the Content Store to work. They are commented out of the default block list; the community blocklists (andlgappupdateblocker) block them, which kills the Content Store. Homebrew Channel installs via the localcom.webos.appInstallService/dev/installpath and keeps working either way. - Voice search breaks if you block
lgsmartweb.com. The voice stack (voiceinput*,trigger_thinq,trigger_alexa, wake wordhiLG) is local, but the NLP/search backends are remote (nextlgsdp.comsdp_nlp,lgsmartweb.com). Local voice commands survive; voice search needs the remote backend.lgsmartweb.comis commented out by default. It isn’t clear what your exposure here is in terms of privacy. I’d recommend not using local voice services. - Never accept an OS update once rooted. The update check runs before
startup.shat boot, so hosts blocking is best-effort for OTA (but the router layer is the real OTA defense). Root persistence across OS updates is not guaranteed (webOS 26 exists for 2026 models). If an update ever slips through, expect to re-root and re-apply everything. - Push notifications via AWS IoT MQTT use a per-device broker certificate (
/mnt/lg/cmn_data/.pushclient/push.cert.pem) with a device-specific*.amazonaws.comhost; do not hosts-blockable. DNS-block*.amazonaws.comonly if you accept collateral damage. - Failsafe mode skips everything. Homebrew Channel has a failsafe flag (
/var/luna/preferences/webosbrew_failsafe) that bypassesstartup.shand while it’s set, Layers 2–5 are inert. Only the router layer still protects you. - Do not block
.lge.comwholesale. It kills the Content Store and other legitimate services. Only the specific*.lge.comsubdomains listed in BLOCKLIST Section are blocked. acr2is currently inert on the test TV (empty solution lib, zeroed DB), so
ACR blocking is preventive, not a fix for an active leak. If you want ACR fully dead, the consent decline + opt-out marker in Layer 4 is how you do that.
Uninstall / rollback
ssh root@(your tv IP)
rm /var/lib/webosbrew/init.d/10-block-lg-telemetry
rm -rf /var/lib/webosbrew/lg-lockout
rm /var/luna/preferences/webosbrew_block_updates
# restore backups from Layer 0.2 if you want the original consents back
cp /tmp/lg-lockout-backup/eula /var/luna/preferences/eula
cp /tmp/lg-lockout-backup/option /var/luna/preferences/option
reboot # clears the hosts bind mount
Or just factory reset and then everything is gone, including root.
WE NOT RESPONSIBLE IF THIS GOES SIDEWAYS. Perform modifications at your own risk.
#BLOCKLIST Section
LG webOS TV — Lockout Blocklist
Target: OLED65G5WUA, webOS 10.2.1 (starfish, build ponytail-paparoa), IP (your TV IP).
All domains below were observed live on this TV on 2026-08-24 (read-only recon) unless
marked community (taken from the cited blocklists, not re-verified on this unit).
Hosts-file entries block exact hostnames only as there are no wildcards in /etc/hosts.
Every subdomain a service uses must be listed individually. For DNS-layer blocking (Pi-hole /
dnsmasq) you may use wildcards where your resolver supports them (marked *).
1. OTA / OS updates
| Domain | What it is | What breaks if blocked |
|---|---|---|
snu.lge.com |
OTA check/feedback (CheckSWAutoUpdate.laf, DownLoadFeedback.laf, …) |
OS auto-update (desired) |
su.lge.com |
OTA download (HTTP) | OS auto-update (desired) |
su-ssl.lge.com |
OTA download (HTTPS) | OS auto-update (desired) |
nsu.lge.com |
OTA (port 5100) | OS auto-update (desired) |
snu-dev.lge.com |
OTA dev endpoint | nothing (dev) |
su-dev.lge.com |
OTA dev endpoint | nothing (dev) |
IP 156.147.69.32:8080 |
Hardcoded OTA fallback IP The domain blocks MISS this | nothing: must be blocked at router/firewall, hosts cannot block an IP |
Source: on-device /usr/sbin/update binary strings + throwaway96/webosbrew (webosbrew.org)
and Informatic/RootMyTV (https://github.com/Informatic/rootmy.tv).
2. SDX telemetry (primary phone-home, /usr/sbin/sdx)
Endpoint map from /mnt/lg/cmn_data/sdp/sdx/server_addr_version.conf (v1.5).
2a. nextlgsdp.com family
| Domain | sdx service |
|---|---|
nextlgsdp.com |
sdp_auth, sdp_init, sdp_common, sdp_logging, sdp_home, sdp_nlp, sdp_onnow, sdp_search, sdp_apps, sdp_apps_resource, sdp_airplay, sdp_nais |
ibs.nextlgsdp.com |
ibis_secure |
ibsstat.nextlgsdp.com |
ibis_stat_secure |
rdx2.nextlgsdp.com |
rdx_secure (also used by uploadd) |
2b. lgtvcommon.com family (* = wildcard-safe in DNS blockers)
| Domain | Service |
|---|---|
lgtvcommon.com * |
base |
netflixvoice.lgtvcommon.com |
voice proxy |
nudge.lgtvcommon.com |
nudge (promo notifications) |
homeprv.lgtvcommon.com |
home provisioning |
wiseconfig.lgtvcommon.com |
smart config |
pnv.lgtvcommon.com |
CPV |
recommend.lgtvcommon.com |
recommendations |
cdpsvc.lgtvcommon.com |
CDP |
cpauth.lgtvcommon.com |
CDP auth |
cdpbeacon.lgtvcommon.com |
CDP beacon |
rdl.lgtvcommon.com |
rdxd crash/analytics upload |
wiseresource.lgtvcommon.com |
wise resource |
qcardservice.lgtvcommon.com |
qcard |
qt2-kic.lab.lgtvcommon.com |
ThinQ AI lab endpoint |
2c. Other SDX endpoints
| Domain | Service |
|---|---|
lgshopsvc.lgappstv.com |
LG Shop |
lggalleryplus.com |
Gallery+ |
tv.wiselg.com |
wise account / buddy |
Live observation: sdx held an outbound HTTPS connection to 54.186.247.229:443 (AWS) at recon time and block that IP at the router as well (it may resolve to other IPs over time, but that’d probably require a firmware update on the TV to reconcile…)
3. ACR (Automatic Content Recognition)
| Domain | What it is | What breaks |
|---|---|---|
| (none currently) | acr2 (/usr/sbin/acr2) is configured (acr.xml ACR_On="true", Alphonso, dsnoop:0,12, client token LG-webOS25-X-54eGHhzNbjzrzgcM) but not running so check the solution lib dir is empty, DB zeroed |
ACR (desired) |
Blocking is not the primary defense for ACR: decline the S_ADG consent and create the
opt-out marker (see decline-tos.sh). If ACR ever starts phoning home it will use the
SDX/nextlgsdp.com path already covered above.
4. Ads
| Domain | What it is | What breaks |
|---|---|---|
lgsmartad.com * |
ad server (base) | ads (desired) |
info.lgsmartad.com |
admanager polls this every ~60s (com.webos.service.admanager) |
ads (desired) |
5. ThinQ / IoT
| Domain | What it is | What breaks |
|---|---|---|
lgtviot.com * |
base | ThinQ app / IoT |
api.lgtviot.com |
iot-client / sdx iot | ThinQ app |
commonpush.lgtviot.com |
iot push | ThinQ push |
sports.lgtviot.com |
iot sports | sports alerts |
ocp.lgtviot.com |
ocpservice | OCP |
push.lgtviot.com |
sportsalarm push | sports alerts |
buddy.lgtviot.com |
buddyconnector | buddy |
lgthinq.com * |
base | ThinQ app |
common.lgthinq.com |
ThinQ common | ThinQ app |
connect-client.lgthinq.com |
ThinQ connect | ThinQ app |
Push notifications (com.webos.service.pushclient) use AWS IoT MQTT with a per-device
certificate (/mnt/lg/cmn_data/.pushclient/push.cert.pem) And the broker hostname is
device-specific (*.iot.<region>.amazonaws.com) and it seems LG has taken steps to ignore the local /etc/hosts for DNS-block. *.amazonaws.com only if you are willing to lose other AWS-reachable features, or use your firewall to suss out what your TV is connecting to at amazonaws.com and then block that.
6. LLM / AI platform (com.webos.app.aiplatform)
| Domain | What it is | What breaks |
|---|---|---|
ngfts.lge.com |
AI platform | AI features (desired) |
qt2-ngfts.lge.com |
AI platform | AI features |
kic-ngfts.lge.com |
AI platform | AI features |
kic-qt2-ngfts.lge.com |
AI platform | AI features |
profile.json on this TV has "llm": {"support": true} so the AI/LLM stack is enabled and
needs these endpoints. Or you can just block them if you don’t want it.
7. Crash / analytics upload
| Domain | What it is | What breaks |
|---|---|---|
rdx2.nextlgsdp.com |
uploadd crash upload | nothing |
rdl.lgtvcommon.com |
rdxd analytics upload (/etc/rdxd.conf AutoUpload=true) |
nothing |
Both uploadd and rdxd were running on this TV. The built-in HBChannel “telemetry neuter”
(read-only bind-mounts over /tmp/rdxd, /tmp/uploadd, /var/spool/rdxd,
/var/spool/uploadd/{pending,uploaded}) stops them from writing – see Layer 2.
8. Voice stack
| Domain | What it is | What breaks |
|---|---|---|
nextlgsdp.com (sdp_nlp) |
voice NLP backend | voice search / assistant |
lgsmartweb.com |
LG web search backend | voice search results |
The voice stack itself (voiceinput*, trigger_thinq, trigger_alexa, voiceconductor,
performer, wake word hiLG) is local; only the NLP/search backends are remote. Blocking
them breaks voice search but not local voice commands. Optional and there are caveats.
9. Content Store / app store – There is a TRADEOFF (optional)
| Domain | What it is | What breaks if blocked |
|---|---|---|
lgtvsdp.com * |
Content Store / app update gate | Content Store breaks; also the mechanism lgappupdateblocker uses to block app-update popups |
lgappstv.com * |
app store / LG Shop | Content Store + app installs break |
lgshopsvc.lgappstv.com |
LG Shop service | LG Shop |
lgtvsdp.com + lgappstv.com are needed for the Content Store to work. Homebrew
Channel installs via com.webos.appInstallService/dev/install (local, no LG network), so
homebrew keeps working regardless. Block these only if you accept losing the Content Store.
Community blocklist sources
These folks are the real MVPs here. Huge Kudos!
Wildcard guidance for DNS-layer blockers
Safe to wildcard: *.nextlgsdp.com, *.lgtvcommon.com, *.lgsmartad.com, *.lgtviot.com,
*.lgthinq.com, *.lgtvsdp.com (tradeoff), *.lgappstv.com (tradeoff).
Do NOT block .lge.com wholesale because it kills the Content Store and other legitimate services. I was surprised in my research how many LG “fans” want to keep using built-in functionality of the TV. Only block the specific *.lge.com subdomains listed above (snu/su/nsu/ngfts).
Remember to rename the files to remove the .txt extension!
10-block-lg-telemetry.txt (5.2 KB)
clear-app-update-gate.sh.txt (1.9 KB)
decline-tos.sh.txt (6.6 KB)
install.sh.txt (4.1 KB)
verify-lockout.sh.txt (4.8 KB)
