Skip to content

Latest commit

 

History

History
126 lines (98 loc) · 5.74 KB

File metadata and controls

126 lines (98 loc) · 5.74 KB

How the webOS settings API actually behaves

Hard-won details, in case you extend this or port it to another model. All of it was measured, not read from documentation — LG publishes none.

Transport

  • webOS 4+ (2018 and later) serves SSAP over TLS on port 3001 and resets connections to the old plaintext 3000. The client tries 3001 first and falls back.
  • The TV presents a self-signed certificate for its own LAN address, so there is nothing to validate it against. Traffic is still encrypted.
  • A silent socket close during registration — no error frame, just a close — is how some firmware rejects a manifest it dislikes. Code that treats a closed socket as a transport failure will report this misleadingly.
  • ssap://system/getSystemInfo answers before registration, unlike almost everything else. That makes it the one useful diagnostic when pairing is broken. SSDP is unauthenticated and also answers when SSAP refuses.

Registration and permissions

The manifest is re-evaluated on every registration. Permissions are not frozen onto the client key at pairing time, so an existing key can present a different scope freely, with no re-pairing and no on-screen prompt.

Measured with one stored key against a 50UR8000PJB (fw 33.31.61):

scope getSystemSettings setSystemSettings
minimal 401 401
full OK 401
signed OK OK
generic OK 401

WRITE_SETTINGS and READ_UPDATE_INFO appear only inside the signature-protected signed block of LG's manifest. The generic shape copies that permission list verbatim but carries no signature, and is still refused — so the signature is genuinely validated for those permissions, rather than the block being read as a claim.

Unrecognised permission names are dropped silently rather than erroring, which is an easy way to end up with a narrower grant than you intended.

The webOS 26 blacklist

webOS 26 (LG firmware 43.00.92+) blacklisted the classic "LG Remote App" identity — appId com.lge.test plus LG's baked-in signature. Pairing with it still returns a client key, so it looks successful, but the TV then grants the key almost nothing and answers 401 insufficient permissions (not registered). On that firmware, presenting LG's signed manifest makes things worse.

The community fix is a signed block with a neutral appId and no signature at all — the generic scope here. References:

ssap://settings/getSystemSettings

  • Needs {"category": X, "keys": [...]} with a non-empty keys array. An empty array returns 500.
  • There is no enumeration. getSystemSettingDesc returns 500 and wildcards are rejected.
  • One bad key poisons the whole batch, so keys must be probed one (category, key) pair at a time. This is why probing is slow.
  • 500 means "no such key", not "forbidden". That asymmetry is what makes blind discovery possible at all: a returned value proves the key exists, and a 500 proves it does not. Do not report a 500 as a permission problem.
  • Object-valued keys (eulaStatus, localeInfo, eulaInfoNetwork) are only readable with no category field at all. Sending category: null is a 500.

ssap://settings/setSystemSettings

  • Writes go here. The com.webos.settingsservice and luna:// variants return 404 — they are not bridged to the network.
  • Requires the signed scope; see above.
  • returnValue: true does not prove persistence. Always read back. This is not hypothetical — it is the single most important thing to know about this API, and the reason every write in this package is verified.
  • Object writes are read-modify-write. It is unknown whether the TV merges or replaces, so writing the full object means every other field survives either way. Check the field count afterwards: a shrunk object means the TV replaced rather than merged.

Error codes

SSAP distinguishes these, and the distinction carries real information:

Code Meaning
404 no such service or method The endpoint does not exist.
401 insufficient permissions It exists, but this manifest cannot reach it.
403 access denied Exists, refused.
500 Application error Exists and ran; the arguments were wrong.

A 401 therefore proves an endpoint exists, which is what makes blind endpoint discovery possible.

Warning: there is no way to test existence without calling. A method that exists and tolerates an empty payload may actually run. Only probe verbs whose effect you are willing to cause.

Setting categories

26 exist on the test set: "" (none), 3d, aiPicture, aspectRatio, caption, channel, commercial, commercialTv, general, hotelMode, lgchannels, lock, musicCatch, network, option, other, picture, push, sound, soundbar, support, time, timemachine, timer, twinTv, voiceframework.

eulaStatus is reachable only with no category, and is absent from every published category list — it was found by probing candidate key names harvested from bscpylgtv's per-model settings dumps.

Power

off is ssap://system/turnOff. on cannot use SSAP at all: a TV in standby has no WebSocket listening, so the only way back up is a Wake-on-LAN magic packet at the network layer, which needs Mobile TV On (Turn on via Wi-Fi on some firmware) enabled on the TV.

The TV reports a MAC for every interface it has — wired, wifi and p2p — and does not say which is active, so tv-privacy power on sends a packet to each. A packet aimed at a down interface is simply ignored.