Skip to content

better JSON parse error handling - #5484

Open
softhack007 wants to merge 8 commits into
mainfrom
json_error_handling
Open

softhack007 wants to merge 8 commits into
mainfrom
json_error_handling

Conversation

@softhack007

@softhack007 softhack007 commented Apr 7, 2026 •

Copy link
Copy Markdown
Member
  • malformed / too big wsec.json and cfg.json are treated as read error
  • log JSON parse errors with DEBUG_PRINT
  • out-of-memory (json buffer) is still accepted for other files (large ledmaps / gapmaps / presets.json)

This is also a security improvement together with #5482

Summary by CodeRabbit

  • Bug Fixes
    • Limits the number of Wi-Fi networks loaded from configuration files.
    • Rejects unreadable, oversized, or empty security configuration files. If the main configuration file cannot be read or exceeds capacity, loading continues without applying its invalid data.
    • Reports JSON parsing errors and returns failure for most malformed files, improving detection of configuration read problems.

* malformed / too big wsec.json and cfg.json are treated as read error
* debug_print JSON parse errors
@softhack007 softhack007 added the bug label Apr 7, 2026
@coderabbitai

coderabbitai Bot commented Apr 7, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • No new commits to review - use @coderabbitai full review for a full pass

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: wled/WLED/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 9d08c5f2-c0cd-420d-af31-5ea21d52f0b9
📥 Commits

Reviewing files that changed from the base of the PR and between 252007d and 3ec8670.

📒 Files selected for processing (2)
  • wled00/cfg.cpp
  • wled00/file.cpp

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.


Walkthrough

JSON file reads now report selected deserialization errors. Configuration loading handles failed or overflowed documents, rejects invalid security configuration, and caps Wi-Fi list resizing at WLED_MAX_WIFI_COUNT.

Changes

Configuration JSON handling

Layer / File(s) Summary
File deserialization results
wled00/file.cpp
readObjectFromFile logs deserialization errors. It returns false for errors other than NoMemory and EmptyInput.
Configuration loading and Wi-Fi limits
wled00/cfg.cpp
deserializeConfigFromFS clears the document when reading cfg.json fails or the document overflows, then continues configuration deserialization. deserializeConfigSec returns false for failed reads, overflow, or documents with fewer than one member. Both Wi-Fi lists cap multiWiFi resizing at WLED_MAX_WIFI_COUNT.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 3ec86

No actionable issue remains from this review; the reported timer ambiguity predates this change and does not block merging it.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to 3ec86

Validation and Wi-Fi limits improve input handling. However, rejecting a partially readable security file can leave a previously PIN-protected device running without its configured PIN. Network exposure depends on connectivity and recovery settings, and a later save can persist that fallback state.

Retained concerns

  • Medium · security · inferred: Security-document rejection is not coupled to a locked recovery state. If a protected wsec.json contains a readable nonempty PIN followed by a parse failure, base could retain that PIN, whereas head rejects it before application and continues startup. Builds using the default empty PIN therefore retain correctPIN=true and allow reachable clients through existing PIN gates. A later configuration save can persist the empty PIN. Missing-file fallback predates this PR, but the newly rejected inputs expand that failure state.
Security review details

Security Blast Radius

  • inferred — The identified failure affects the configuration authority of one device after a rejected security file and reboot. Exploitation requires subsequent network reachability. If lost Wi-Fi credentials cause connection failure and the saved AP policy permits fallback, the device can expose its HTTP server through an AP using the retained default password. The inspected upload path requires an unlocked PIN state; unauthenticated creation of the corrupt file was not established.

Security Findings and Attack Paths

  • inferred — The retained finding collection is empty. Static inspection nevertheless identifies a conditional recovery regression: a parser error after an already parsed PIN now prevents PIN application, startup continues with the default authorized state, and a reachable client can access operations guarded only by correctPIN. This is not a claim that ordinary clients can induce the prerequisite corruption.

Trust Boundaries and Controls

  • observed — The upload PIN check remains present. Compile-time PIN overrides can preserve protection after security-read rejection. OTA/Wi-Fi locks are also mirrored into cfg.json and can be restored through its existing guarded loader, while firmware uploads retain subnet, PIN and OTA-lock checks. These controls limit the concern and do not support an unconditional firmware-update bypass.

Resilience and Maintainability Implications

  • observed — The existing save sequence writes wsec.json from current globals before backing up and writing cfg.json. Security-file writing uses direct write-mode replacement, without a rejected-load marker or a security-file backup in this sequence. These persistence characteristics predate the PR but interact with its expanded rejection policy.

Hardening Proposals

  • proposed — Represent rejected security configuration as an explicit recovery state. Preserve a validated last-known-good security configuration or restrict privileged operations until deliberate reprovisioning, and prevent routine configuration saves from silently persisting unvalidated fallback credentials. This need not restore acceptance of partially parsed security documents.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: improved JSON parse error handling.
  • Fix all pre-merge checks with AI

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

@softhack007 softhack007 assigned DedeHai and willmmiles and unassigned DedeHai and willmmiles Apr 7, 2026
Comment thread wled00/cfg.cpp Outdated
coderabbitai[bot]

This comment was marked as outdated.

Comment thread wled00/cfg.cpp
Comment thread wled00/cfg.cpp
success = readObjectFromFile(s_cfg_json, nullptr, pDoc);

bool success = readObjectFromFile(s_cfg_json, nullptr, pDoc);
if (!success || (pDoc->overflowed())) pDoc->clear(); // corrupted/too-large → same as missing: seed defaults

@DedeHai DedeHai Apr 7, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could restore the backup first before giving up but need to check that will not result in an infinite loop

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point 👍 can you look into that? I'm quite busy atm with holiday trip preparations 😃

@softhack007

This comment was marked as outdated.

@softhack007

This comment was marked as outdated.

@coderabbitai

This comment was marked as outdated.

@softhack007 softhack007 added this to the 16.1 milestone May 3, 2026
@softhack007 softhack007 modified the milestones: 16.1, 16.0.0 beta May 11, 2026
softhack007 added a commit that referenced this pull request May 24, 2026
* require access to /edit for uploading
* JSON validation improvements are tracked in #5484 / #5482.
@softhack007

softhack007 commented Jun 14, 2026 •

Copy link
Copy Markdown
Member Author

This is a robustness improvement - the original problem always existed so not a regression w.r.t. 0.15.x. Would be ok for me if we move this PR to 16.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants