As of 15 October 2026, no product can carry the U.S. Cyber Trust Mark. The FCC adopted the rules for its voluntary IoT security label in March 2024. On 28 September 2026 it recognised the two bodies that will accredit the program's testing labs and label administrators. But the technical standard products will be tested against still hasn't been adopted, so nobody can be accredited to it and nobody can apply.
This post is for product security and firmware teams at companies that make connected consumer devices, and for anyone asked "should we get the Cyber Trust Mark?". It covers what's in place, what still has to happen, what the rules already commit a manufacturer to, and what the 133-page draft standard asks for. It ends with a script that checks the parts you can test today.
The short answer
The U.S. Cyber Trust Mark is the FCC's voluntary security label for consumer wireless IoT products: a shield logo plus a QR code linking to a public registry entry. On 15 October 2026 it can't be applied for. The FCC has a Lead Administrator (ioXt Alliance, since April 2026), conditionally approved label administrators, and recognised accreditation bodies (A2LA and ANAB, since 28 September 2026). It hasn't adopted the standard and test procedures. A draft standard submitted in June 2025 shows what to expect: binary pass/fail controls based on NIST IR 8425, a published support end date, signed updates, a vulnerability reporting route and an SBOM or equivalent inventory. The FCC will announce when applications open.
What the program is
The program covers consumer IoT products with an intentional radio and at least one sensor or actuator, together with the companion app, hub and cloud backend needed to use them. It excludes FDA-regulated medical devices, vehicles regulated by NHTSA, wired-only devices and products meant for industrial or enterprise use. It also bars anything made by companies on the FCC's Covered List, the Commerce Department's Entity List or the Defense Department's list of Chinese military companies, or by suspended or debarred entities (47 CFR 8.204).
Four kinds of organisation run it under FCC oversight:
| Role | Job | Status on 15 October 2026 |
|---|---|---|
| Lead Administrator | Recommends standards, test procedures and label design; runs consumer education; recognises labs | ioXt Alliance, selected 13 April 2026 |
| Cybersecurity Label Administrators (CLAs) | Review applications and grant or deny use of the label | Conditionally approved; none can grant yet |
| CyberLABs | Test products against the standard | None accredited, because the standard isn't adopted |
| Accreditation bodies | Accredit CLAs (ISO/IEC 17065) and labs (ISO/IEC 17025) | A2LA and ANAB, recognised 28 September 2026 |
A product that passes gets the label on its packaging. The QR code leads to a registry entry with the support end date, update method and other details. The FCC's own program page compares the idea to ENERGY STAR.
How it got here
| Date | Event | Source |
|---|---|---|
| March 2024 | FCC adopts the rules and a further notice on national security disclosures | IoT Labeling Order, FCC 24-26 |
| 4 and 11 December 2024 | UL selected as Lead Administrator; 11 CLAs conditionally approved | DA 24-1241 |
| 13 June 2025 | Lead Administrator files its recommended standard, label design and renewal rules | ECFS filing |
| 15 August 2025 | CTIA Certification withdraws as a CLA | DA 26-75 |
| 19 December 2025 | UL Solutions withdraws as Lead Administrator | DA 26-18 |
| 13 April 2026 | ioXt Alliance selected as the new Lead Administrator | DA 26-354 |
| 11 August 2026 | Two more CLAs conditionally approved; CLA filing window reopened with no closing date | DA 26-834 |
| 28 September 2026 | A2LA and ANAB recognised as accreditation bodies | DA 26-1029 |
The program lost its first Lead Administrator and spent most of the first half of 2026 replacing it. The FCC's April announcement says the Commission has worked to advance the program "with a greater emphasis on national security" under Chairman Brendan Carr.
What still has to happen before anyone can apply
The FCC's program page sets out the remaining steps:
- The Lead Administrator recommends standards and test procedures for at least one class of product. The June 2025 recommendations exist. ioXt's April selection notice says the Bureau is reviewing them and will put them out for public comment, which hadn't happened by 15 October.
- After comments close, the Bureau adopts the standards and test procedures in an order that also sets the program's scope.
- A2LA and ANAB accredit CLAs and labs to that scope. The rules give conditionally approved CLAs six months from the date the standards take effect to get accredited.
- The Bureau announces each CLA's full approval, and the Lead Administrator recognises accredited labs. Only then can manufacturers apply.
The FCC is also still reviewing comments on possible extra national security disclosures. It hasn't published a target date, and we won't guess one.
What the rules already commit a manufacturer to
These parts are adopted and in the Code of Federal Regulations. Nothing in Part 8, Subpart B has changed since November 2024.
A declaration under penalty of perjury (8.208(c)). Besides confirming the product isn't from an excluded source, the applicant declares that it "has taken every reasonable measure to create a securable product". It also declares that until the support end date in the registry it will diligently identify critical vulnerabilities and promptly issue updates that fix them. A further clause says the applicant won't disclaim or limit the enforceability of that declaration anywhere else, so the terms of service can't quietly walk it back.
A public registry entry (8.222(b)) with ten fields: product and manufacturer names, authorisation date and status, the CLA, the testing lab, how to change the default password, secure configuration guidance, whether updates are automatic, the support end date (or a plain statement that the product is unsupported), and whether the manufacturer keeps a software or hardware bill of materials.
A U.S. agent for service of process, records of design changes and test results kept for two years after the product is discontinued, and, if the FCC finds a complaint about the product justified, it can order the manufacturer to investigate and report back within 20 days. The FCC can terminate a label grant for false statements or non-conformity.
The registry asks whether an SBOM exists, not for the SBOM itself. But the support end date and the patching promise are commitments made in public, with the FCC as the enforcer.
What the draft standard asks for
The June 2025 recommendations include the "Consumer IoT Cybersecurity Standard", version 1.0, built on NIST IR 8425. It hasn't been adopted, and ioXt and the public comment process may change it. It's still the best guide to what testing will look like. The points that matter most for engineering teams:
- Every control is pass or fail. The document says a risk assessment "must never waive" a control or justify partly meeting it.
- Component inventory (DOC-1B). A statement that the manufacturer keeps an SBOM, HBOM or equivalent inventory covering hardware, firmware, OS, applications and third-party libraries.
- Support period (DOC-1F). A minimum security support period with clear start and end dates, published in plain language before purchase, plus a process for warning users before it ends.
- Vulnerability management (DOC-1G). A documented process with a defined scanning frequency and a check against public exploit data such as CISA KEV. The lab will ask for scan results and mitigation records from the last three months. You also need a security contact that researchers can find (the draft gives security.txt as an example) and a disclosure policy.
- Updates (SUP-01, SUP-02). Updates must be signed and verified, and the lab will try installing an unsigned or tampered package, which must be rejected. Automatic security updates are required, with user notification where they're turned off.
- Passwords. Default passwords must be unique per device, or the user must be forced to change them on first use. Brute-force protection is tested.
- Cloud backend. Rather than testing the cloud itself, the lab accepts a current certificate covering every backend component. Accepted programs are CASA Level 2+, CSA STAR Level 2+, SOC 2 Type II plus annual third-party penetration testing, FedRAMP Moderate or High, or ISO/IEC 27001.
- Deprecated technology (Annex 1). TLS 1.2 or later only, with SSL, TLS 1.0 and TLS 1.1 disabled, and no RSA key exchange, static Diffie-Hellman, RC4, 3DES or export suites.
The draft also narrows the scope beyond the rules. It excludes devices that run third-party apps, home routers, PCs, phones, and distributed energy equipment such as solar inverters and EV chargers. A companion renewal document has products recertify every five years, with at least half of the requirements re-tested each time.
Check what you can today
Most of this can't be tested until the standard is final. A few parts can, because they don't depend on the final wording: the registry fields in the rule, a findable security contact, and the TLS baseline. This script checks all three. It takes a draft registry record as JSON, the domain where your security.txt should live, and any device or backend TLS endpoints. It uses only the Python standard library, and exits 1 if it finds a problem.
#!/usr/bin/env python3
"""Pre-check a consumer IoT product against parts of the U.S. Cyber Trust Mark rules.
Checks three things a product team can test today:
--record FILE a draft registry record against 47 CFR 8.222(b)
--domain NAME the manufacturer's security.txt (RFC 9116), for vulnerability reports
--tls HOST:PORT a backend or device TLS endpoint against the draft standard's
Annex 1 (no SSL/TLS 1.0/1.1, no RSA key exchange)
The registry fields come from the adopted rule. The TLS and security.txt checks
follow the Lead Administrator's June 2025 draft standard, which the FCC has not
adopted yet. Standard library only.
"""
import argparse, datetime as dt, json, socket, ssl, sys, urllib.request, warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
TODAY = dt.date.today()
# 47 CFR 8.222(b)(1)-(10), in the rule's order
REGISTRY_FIELDS = [
("product_name", "(1) product name"),
("manufacturer", "(2) manufacturer name"),
("authorization_date", "(3) date of authorization and status"),
("cla", "(4) CLA name and contact"),
("cyberlab", "(5) lab that did the testing"),
("default_password_instructions", "(6) how to change the default password"),
("secure_configuration_url", "(7) secure configuration guidance"),
("update_method", "(8) automatic updates, or how to get them"),
("support_end_date", "(9) minimum support period end date"),
("sbom_maintained", "(10) SBOM and/or HBOM maintained?"),
]
PRE_GRANT = {"authorization_date", "cla", "cyberlab"} # unknown until a CLA grants
def check_record(path):
rec = json.load(open(path))
problems = 0
for key, label in REGISTRY_FIELDS:
val = rec.get(key)
if val in (None, "", []):
if key in PRE_GRANT:
print(f" [later] {label}: filled in after a CLA grants the label")
continue
print(f" [MISSING] {label}")
problems += 1
continue
if key == "support_end_date":
if str(val).lower() == "unsupported":
print(f" [WARN] {label}: product declared unsupported; registry must say so plainly")
continue
try:
end = dt.date.fromisoformat(str(val))
except ValueError:
print(f" [FAIL] {label}: '{val}' is not a date (YYYY-MM-DD) or 'unsupported'")
problems += 1
continue
left = (end - TODAY).days
if left < 0:
print(f" [FAIL] {label}: {end} has already passed")
problems += 1
elif left < 365:
print(f" [WARN] {label}: {end}, only {left} days away")
else:
print(f" [ok] {label}: {end} ({left // 365} years {left % 365} days away)")
continue
if key == "sbom_maintained" and not isinstance(val, dict):
print(f" [FAIL] {label}: give {{\"sbom\": true/false, \"hbom\": true/false}}")
problems += 1
continue
print(f" [ok] {label}")
return problems
def check_security_txt(domain):
url = f"https://{domain}/.well-known/security.txt"
try:
req = urllib.request.Request(url, headers={"User-Agent": "usctm-readiness/1.0"})
with urllib.request.urlopen(req, timeout=10) as r:
text = r.read(65536).decode("utf-8", "replace")
ctype = r.headers.get("Content-Type", "")
except Exception as e:
print(f" [FAIL] {url}: {type(e).__name__} {str(e)[:60]}")
return 1
fields = {}
for line in text.splitlines():
if ":" in line and not line.startswith("#"):
k, v = line.split(":", 1)
fields.setdefault(k.strip().lower(), []).append(v.strip())
problems = 0
if not ctype.startswith("text/plain"):
print(f" [WARN] Content-Type is '{ctype}', RFC 9116 wants text/plain")
if "contact" not in fields:
print(" [FAIL] no Contact field")
problems += 1
else:
print(f" [ok] Contact: {', '.join(fields['contact'])[:70]}")
if "expires" not in fields:
print(" [FAIL] no Expires field (required by RFC 9116)")
problems += 1
else:
raw = fields["expires"][0]
try:
exp = dt.datetime.fromisoformat(raw.replace("Z", "+00:00")).date()
if exp < TODAY:
print(f" [FAIL] Expires {exp} has passed")
problems += 1
else:
print(f" [ok] Expires {exp}")
except ValueError:
print(f" [FAIL] Expires '{raw}' is not an RFC 3339 date")
problems += 1
if "policy" in fields:
print(f" [ok] Policy: {fields['policy'][0][:70]}")
else:
print(" [WARN] no Policy field; the draft standard asks for a documented disclosure policy")
return problems
def handshake(host, port, version, ciphers="ALL:@SECLEVEL=0"):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname, ctx.verify_mode = False, ssl.CERT_NONE
ctx.set_ciphers(ciphers)
ctx.minimum_version = ctx.maximum_version = version
try:
with socket.create_connection((host, port), timeout=8) as s:
with ctx.wrap_socket(s, server_hostname=host) as t:
return t.cipher()[0]
except (ssl.SSLError, ConnectionError, socket.timeout, OSError):
return None
def check_tls(target):
host, _, port = target.partition(":")
port = int(port or 443)
V = ssl.TLSVersion
problems = 0
for name, ver in (("TLS 1.0", V.TLSv1), ("TLS 1.1", V.TLSv1_1)):
c = handshake(host, port, ver)
if c:
print(f" [FAIL] accepts {name} ({c}); Annex 1 says disable it")
problems += 1
else:
print(f" [ok] refuses {name}")
c12 = handshake(host, port, V.TLSv1_2)
c13 = handshake(host, port, V.TLSv1_3)
if not (c12 or c13):
print(" [FAIL] no TLS 1.2 or 1.3 handshake succeeded")
return problems + 1
print(f" [ok] TLS 1.2: {c12 or 'not offered'}; TLS 1.3: {c13 or 'not offered'}")
if c12:
rsa = handshake(host, port, V.TLSv1_2, "kRSA:@SECLEVEL=0")
if rsa:
print(f" [FAIL] accepts RSA key exchange ({rsa}); Annex 1 lists it as obsolete")
problems += 1
else:
print(" [ok] refuses RSA key exchange suites")
return problems
def main():
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
ap.add_argument("--record")
ap.add_argument("--domain")
ap.add_argument("--tls", action="append", default=[])
a = ap.parse_args()
total = 0
if a.record:
print(f"Registry record {a.record} (47 CFR 8.222(b)):")
total += check_record(a.record)
if a.domain:
print(f"security.txt for {a.domain}:")
total += check_security_txt(a.domain)
for t in a.tls:
print(f"TLS {t}:")
total += check_tls(t)
print(f"\n{total} problem(s) found")
sys.exit(1 if total else 0)
if __name__ == "__main__":
main()
The example record is for a fictional indoor camera:
{
"product_name": "Example Cam 2 (indoor Wi-Fi camera)",
"manufacturer": "Example Devices Inc.",
"authorization_date": null,
"cla": null,
"cyberlab": null,
"default_password_instructions": "Each camera ships with a unique password printed on the base. Change it in the app under Settings > Device > Password.",
"secure_configuration_url": "",
"update_method": "Automatic. Firmware updates install overnight; turn this off under Settings > Updates.",
"support_end_date": "2031-06-30",
"sbom_maintained": {"sbom": true, "hbom": false}
}
We ran it on 15 October against that record, the security.txt project's own domain, and two of badssl.com's deliberately misconfigured test servers:
Registry record camera-record.json (47 CFR 8.222(b)):
[ok] (1) product name
[ok] (2) manufacturer name
[later] (3) date of authorization and status: filled in after a CLA grants the label
[later] (4) CLA name and contact: filled in after a CLA grants the label
[later] (5) lab that did the testing: filled in after a CLA grants the label
[ok] (6) how to change the default password
[MISSING] (7) secure configuration guidance
[ok] (8) automatic updates, or how to get them
[ok] (9) minimum support period end date: 2031-06-30 (4 years 259 days away)
[ok] (10) SBOM and/or HBOM maintained?
security.txt for securitytxt.org:
[ok] Contact: https://hackerone.com/ed
[ok] Expires 2027-09-07
[ok] Policy: https://hackerone.com/ed?type=team&view_policy=true
TLS tls-v1-0.badssl.com:1010:
[FAIL] accepts TLS 1.0 (ECDHE-RSA-AES256-SHA); Annex 1 says disable it
[ok] refuses TLS 1.1
[FAIL] no TLS 1.2 or 1.3 handshake succeeded
TLS tls-v1-2.badssl.com:1012:
[ok] refuses TLS 1.0
[ok] refuses TLS 1.1
[ok] TLS 1.2: ECDHE-RSA-AES256-GCM-SHA384; TLS 1.3: not offered
[FAIL] accepts RSA key exchange (AES256-GCM-SHA384); Annex 1 lists it as obsolete
4 problem(s) found
The record has a gap, the security.txt passes, and both TLS servers fail Annex 1. The RSA key exchange rule is stricter than common practice. A major CDN's homepage we tried also still accepts RSA key exchange for old clients. Device firmware and IoT backends with no old clients to support can drop it.
How it compares with mandatory rules
The Cyber Trust Mark is voluntary. Several of the markets you sell into have binding rules already. The UK's PSTI regime has applied since 29 April 2024 (see our review of its first year). Australia's smart device standard has applied since 4 March 2026. The EU Cyber Resilience Act's vulnerability reporting duty started on 11 September 2026, and its main requirements apply from 11 December 2027. All of these ask for some version of no universal default passwords, a published support period and a vulnerability reporting route, which are also central to the U.S. draft. Firmware SBOMs for those regimes are covered in our firmware SBOM guide.
The fair view
There are good reasons to be sceptical. The label is voluntary and slow. It has lost a Lead Administrator and a label administrator, and two and a half years after adoption it still has no adopted standard. Many manufacturers will reasonably wait for retailers or federal buyers to ask for it. The national security exclusions are broad and affect component suppliers too, which shrinks the pool of eligible products.
Even so, the work it requires is worth doing now, and most of it isn't wasted if the U.S. label stalls. A support end date you can defend, a documented vulnerability process with evidence, signed updates, unique credentials and an up-to-date component inventory are what the UK, EU and Australian rules ask for too. If the label does launch, the registry turns the support date into a sworn, public promise. That makes the date worth choosing carefully now, before marketing picks one for you.