Skip to content

fix: URL-decode WiFi passwords before truncating to buffer size#184

Merged
muness merged 2 commits into
masterfrom
fix/wifi-password-url-decode-v3
Mar 22, 2026
Merged

fix: URL-decode WiFi passwords before truncating to buffer size#184
muness merged 2 commits into
masterfrom
fix/wifi-password-url-decode-v3

Conversation

@muness

@muness muness commented Mar 21, 2026

Copy link
Copy Markdown
Owner

Summary

  • WiFi passwords with special characters silently corrupted during captive portal setup
  • URL-encoded data truncated to 65 bytes before decoding — special chars expand 3x, get chopped, decode to garbage → "Wrong Password"
  • Fix: decode into intermediate 256-byte buffer first, then truncate the decoded result
  • Suppresses -Werror=stringop-truncation for newer GCC (will be removed with ESP-IDF 6.0 migration, Upgrade to ESP-IDF v6.0 (stable) #183)

Test plan

  • Flash and connect with short simple password
  • Connect with 63-character password containing special characters (!@#$%^&*)
  • Verify bridge reachable after connecting

Closes #179

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Safer handling of URL-encoded form fields in the captive portal and configuration server to avoid buffer overruns when decoding and truncating input.
  • Chores
    • Adjusted a component-level compiler option to relax treating certain string truncation warnings as errors during build.

WiFi passwords with special characters were silently corrupted during
captive portal setup. URL-encoded data (e.g. ! -> %21) was truncated
to fit the 65-byte output buffer before decoding, so a 63-char password
with special chars could expand to ~107 encoded bytes, get chopped, then
decode to ~40 garbage characters causing "Wrong Password" failures.

Fix: decode into an intermediate 256-byte buffer first, then truncate
the decoded result to fit the output buffer.

Also suppresses -Werror=stringop-truncation for newer GCC toolchains.

Closes #179

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 21, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bd9a7bab-b1f3-43bf-8a4f-b20fc14d0451

📥 Commits

Reviewing files that changed from the base of the PR and between 1557bf8 and ee40bce.

📒 Files selected for processing (1)
  • idf_app/main/CMakeLists.txt
✅ Files skipped from review due to trivial changes (1)
  • idf_app/main/CMakeLists.txt

📝 Walkthrough

Walkthrough

Defers truncation until after URL-decoding when extracting form fields: encoded segments are copied into a 256-byte temporary buffer, URL-decoded, then safely truncated/copyed into the output buffer. Also adds a per-component compiler option to disable treating stringop-truncation as an error.

Changes

Cohort / File(s) Summary
Compiler Configuration
idf_app/main/CMakeLists.txt
Added component-level compile option -Wno-error=stringop-truncation to avoid treating stringop truncation warnings as errors.
Form Field Parsing
idf_app/main/captive_portal.c, idf_app/main/config_server.c
Reworked get_form_field() to copy the raw URL-encoded substring into a fixed 256-byte encoded buffer, run url_decode() on it, then copy/truncate the decoded result into the destination with proper bounds checking and NUL-termination (truncation now occurs after decode).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nibbled bytes in moonlit code tonight,
Pulled encoded crumbs into a safer light,
Decode then cut — no more lost keys,
Hopping past truncation with graceful ease. 🥕🔑

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses the core fix from #179 for two affected files (captive_portal.c and config_server.c), implementing intermediate buffer decoding before truncation as specified. The PR only fixes captive_portal.c and config_server.c in idf_app/main but omits the fix for frame_app/main/captive_portal.c, which has the same vulnerability per issue #179.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: fixing URL-decode truncation behavior for WiFi passwords.
Out of Scope Changes check ✅ Passed CMakeLists.txt compiler flag suppression is a reasonable, documented workaround for newer GCC compatibility issues identified in PR objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/wifi-password-url-decode-v3

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
idf_app/main/captive_portal.c (1)

80-130: Consider consolidating duplicate url_decode() and get_form_field() utilities.

Both captive_portal.c and config_server.c now have identical implementations of these functions. If you prefer DRY over code locality, these could be extracted to a shared header or utility file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@idf_app/main/captive_portal.c` around lines 80 - 130, The url_decode and
get_form_field implementations are duplicated; extract them into a single shared
utility (e.g., a new utils module) and replace the local functions with
declarations that call the shared implementations. Create a header exposing
url_decode(char *str) and get_form_field(const char *data, const char *field,
char *out, size_t out_len), move the current logic from captive_portal.c into
the new source file, update captive_portal.c (and config_server.c) to include
the new header and remove the local definitions, and ensure function signatures
and behavior remain identical so callers need no other changes.
idf_app/main/CMakeLists.txt (1)

72-72: Consider adding a tracking comment for future removal.

The flag suppression is appropriate for the new truncation pattern. Since the PR notes this is temporary until ESP-IDF 6.0, consider adding an inline comment to ensure it's not forgotten:

-target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=stringop-truncation)
+# TODO: Remove after ESP-IDF 6.0 migration (see PR `#184`)
+target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=stringop-truncation)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@idf_app/main/CMakeLists.txt` at line 72, Add an inline tracking comment next
to the target_compile_options(${COMPONENT_LIB} PRIVATE
-Wno-error=stringop-truncation) invocation so future readers know this
suppression is temporary and should be removed when upgrading to ESP-IDF 6.0;
reference the COMPONENT_LIB target and the -Wno-error=stringop-truncation flag
in the comment and include a TODO with a version marker (e.g., TODO: remove when
ESP-IDF >= 6.0) and optionally a short reason why it was added (truncation
pattern).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@idf_app/main/captive_portal.c`:
- Around line 80-130: The url_decode and get_form_field implementations are
duplicated; extract them into a single shared utility (e.g., a new utils module)
and replace the local functions with declarations that call the shared
implementations. Create a header exposing url_decode(char *str) and
get_form_field(const char *data, const char *field, char *out, size_t out_len),
move the current logic from captive_portal.c into the new source file, update
captive_portal.c (and config_server.c) to include the new header and remove the
local definitions, and ensure function signatures and behavior remain identical
so callers need no other changes.

In `@idf_app/main/CMakeLists.txt`:
- Line 72: Add an inline tracking comment next to the
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=stringop-truncation)
invocation so future readers know this suppression is temporary and should be
removed when upgrading to ESP-IDF 6.0; reference the COMPONENT_LIB target and
the -Wno-error=stringop-truncation flag in the comment and include a TODO with a
version marker (e.g., TODO: remove when ESP-IDF >= 6.0) and optionally a short
reason why it was added (truncation pattern).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 102350eb-974c-4ea0-8298-0c3c0508df64

📥 Commits

Reviewing files that changed from the base of the PR and between 13b8630 and 1557bf8.

📒 Files selected for processing (3)
  • idf_app/main/CMakeLists.txt
  • idf_app/main/captive_portal.c
  • idf_app/main/config_server.c

@github-actions

github-actions Bot commented Mar 21, 2026

Copy link
Copy Markdown

Firmware Preview

Flash this PR's firmware directly in your browser:
https://roon-knob.muness.com/pr/184/flash.html

Updated: 2026-03-21T16:18:17.284Z

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@muness muness merged commit bc700e9 into master Mar 22, 2026
6 checks passed
@muness muness deleted the fix/wifi-password-url-decode-v3 branch March 22, 2026 23:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WiFi passwords with special characters silently corrupted during setup

1 participant