Skip to content

Commit 58bf4c8

Browse files
Copilotsofthack007coderabbitai[bot]
authored
add secure coding guides for AI reviews (#5572)
Added security review guidelines and a short checklist covering critical security areas including buffer safety, input validation, authentication, secure defaults, and protection against common vulnerabilities. Refined rule wording and priorities to better fit WLED’s technical constraints and realistic deployment model. The lists are based on the OWASP "top 10" from https://github.com/github/awesome-copilot/blob/main/instructions/security-and-owasp.instructions.md, and on lessons learned from past reviews. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: softhack007 <91616163+softhack007@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 69c2b2d commit 58bf4c8

4 files changed

Lines changed: 437 additions & 16 deletions

File tree

.coderabbit.yaml

Lines changed: 133 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
# docs/cpp.instructions.md — C++ coding conventions
77
# docs/web.instructions.md — Web UI coding conventions
88
# docs/cicd.instructions.md — GitHub Actions / CI-CD conventions
9+
# docs/hardening.instructions.md — basic rules for code hardening and robustness
10+
# docs/securecode.instructions.md — more detailed checklists for common vulnerabilities
911
#
1012
# NOTE: This file must be committed (tracked by git) for CodeRabbit to read
1113
# it from the repository. If it is listed in .gitignore, CodeRabbit will
@@ -54,15 +56,50 @@ reviews:
5456
6. CHECK for implied but weakly justified assumptions - like usermod loop() call frequency - and ask for clarification.
5557
7. FLAG changes that appear unrelated: deleted comments, unnecessary re-formatting or re-factoring, and modifications in files that seem unrelated to the PR description.
5658
59+
# ── Security hardening — firmware (trust-boundary-aware) ────────────────
60+
- path: "wled00/**/*.{cpp,h,hpp,ino}"
61+
instructions: >
62+
Apply the WLED security hardening rules from docs/hardening.instructions.md,
63+
and consult docs/securecode.instructions.md when more details are needed for actionable recommendations.
64+
65+
Trust Boundary Model — enforce input-validation and bounds-checking rules
66+
ONLY at the first untrusted ingress point. Untrusted ingress points are:
67+
- HTTP/JSON API request bodies and query parameters (/json/*, /win, etc.)
68+
- WebSocket message payloads
69+
- UDP datagrams (parsePacket() / recvfrom() and protocol wrappers for
70+
E1.31, DDP, Art-Net, TPM2.net)
71+
- TCP socket reads
72+
- Serial/UART command input
73+
- ESP-NOW raw messages input
74+
75+
A value that has been validated and range-clamped at its ingress handler is
76+
considered TRUSTED for all subsequent WLED core processing. Do NOT flag or suggest
77+
repeated bounds/range checks or internal uses of already-sanitized data.
78+
When it is unclear whether a value has been sanitized upstream, prefer
79+
requesting clarification over raising a false-positive finding.
80+
5781
- path: "wled00/data/**"
5882
instructions: >
5983
Follow the web UI conventions documented in docs/web.instructions.md.
6084
6185
Key rules: indent HTML and JavaScript with tabs, CSS with tabs.
6286
Files here are built into wled00/html_*.h and wled00/js_*.h by tools/cdata.js — never
6387
edit those generated headers directly.
64-
# disabled - the below instruction has no effect
65-
# When initially reviewing a PR, summarize good practices (top 5) and create a prioritized list of suggested improvements (focus on major ones).
88+
89+
# ── Security hardening — WebUI (always an ingress/output surface) ────────
90+
- path: "wled00/data/**"
91+
instructions: >
92+
Apply the WLED web UI security rules from docs/securecode.instructions.md
93+
(sections WEB1-WEB7).
94+
95+
The Trust Boundary Model does NOT reduce scope here: the WebUI is both
96+
an ingress point (user input, postMessage, fetched config data) and an
97+
output/rendering surface. Always flag DOM XSS risks, unsafe
98+
innerHTML / document.write / insertAdjacentHTML / outerHTML assignments,
99+
postMessage handlers without origin validation, eval() / new Function(),
100+
unsafe location.href or location.replace() assignments, and DOM insertion
101+
from fetched or config-derived data — regardless of where the data
102+
originates.
66103
67104
- path: "wled00/html_*.h"
68105
instructions: >
@@ -82,8 +119,33 @@ reviews:
82119
Each usermod lives in its own directory under usermods/ and is implemented
83120
as a .cpp file with a dedicated library.json file to manage dependencies.
84121
Follow the same C++ conventions as the core firmware (docs/cpp.instructions.md).
85-
# disabled - the below instruction has no effect
86-
# When initially reviewing a PR, summarize good practices (top 6) and create a prioritized list of suggested improvements (skip minor ones).
122+
123+
# ── Security hardening — usermods (trust-boundary-aware, narrow scope) ───
124+
- path: "usermods/**/*.{cpp,h,hpp}"
125+
instructions: >
126+
For usermods, the untrusted ingress points are:
127+
- readFromConfig(JsonObject& root) and calls to getJsonValue()
128+
- readFromJsonState(JsonObject& obj) — JSON is parsed, but values are client-supplied
129+
- onMqttMessage(char* topic, char* payload) — raw network strings, no core sanitization
130+
- onEspNowMessage(uint8_t* sender, uint8_t* payload, uint8_t len) — raw radio bytes
131+
- onUdpPacket(uint8_t* payload, size_t len) — raw UDP buffer, no core filtering
132+
Values retrieved at these ingress points are considered trusted only after the
133+
usermod itself has validated and range-clamped them.
134+
135+
Flag ONLY downstream uses of ingress-derived values where an out-of-range or
136+
unexpected value can cause misbehaviour that is not already guarded, for example:
137+
- `switch` statements on an ingress-derived value with no `default` branch,
138+
or with a missing `break` where fall-through is unintentional
139+
- array or buffer indexing with an ingress-derived value where the index is
140+
not clamped before use
141+
- arithmetic with an ingress-derived value that can overflow or produce a
142+
negative result used as a size or count
143+
144+
Do NOT flag:
145+
- getJsonValue() call sites themselves (type coercion is handled by ArduinoJson)
146+
- Internal logic that operates on values already confirmed safe at ingress
147+
- Repeated range checks on values that have already been clamped
148+
- General memory-safety patterns unrelated to ingress-derived data flow
87149
88150
- path: ".github/workflows/*.{yml,yaml}"
89151
instructions: >
@@ -95,8 +157,6 @@ reviews:
95157
scoped to least privilege. Never interpolate github.event.* values directly
96158
into run: steps — pass them through an env: variable to prevent script
97159
injection. Do not use pull_request_target unless fully justified.
98-
# disabled - the below instruction has no effect
99-
# When initially reviewing a PR, summarize good practices (top 6) and create a prioritized list of suggested improvements.
100160
101161
- path: "**/*.instructions.md"
102162
instructions: |
@@ -114,6 +174,73 @@ reviews:
114174
3. If new AI-facing rules were added without updating a related HUMAN_ONLY
115175
reference section, note this as a suggestion (not a required fix).
116176
177+
# ── Secrets / sensitive information scanning ────────────────────────────
178+
- path: "platformio*.ini*"
179+
instructions: >
180+
Scan for secrets, passwords, and other sensitive information accidentally
181+
committed to PlatformIO configuration files (platformio.ini,
182+
platformio_override.ini, platformio_override.ini.sample).
183+
184+
Flag any of the following:
185+
- build_flags entries that define credentials as literal values, e.g.:
186+
-DWIFI_SSID=\"<YOUR_SSID>\" -DWIFI_PASS=\"<YOUR_PASSWORD>\"
187+
-DOTA_PASS=\"<OTA_PASSWORD>\" -DMQTT_PASS=\"<MQTT_PASSWORD>\"
188+
Flag only when the value is not a recognisable placeholder (see below).
189+
- upload_flags or upload_port values that embed a password or auth token (e.g., --auth=<PASSWORD> or any URL using credential-bearing userinfo).
190+
- Any key = <value> pair whose key name contains "pass", "password",
191+
"secret", "token", "key", "credential", or "auth" where the value is
192+
a non-empty, non-placeholder literal string.
193+
- Hardcoded IP addresses or hostnames paired with credentials in the
194+
same environment section.
195+
- API keys or access tokens as literal strings in any field.
196+
197+
Do NOT flag:
198+
- Values that are clearly template placeholders (e.g., YOUR_SSID,
199+
<YOUR_PASSWORD>, changeme, example_token, your_password_here).
200+
- Values that use PlatformIO environment variable substitution (${sysenv.WIFI_PASS} or ${env:WIFI_PASS}).
201+
- Comments that only explain what a field should contain.
202+
- platformio_override.ini.sample entries that contain only
203+
placeholder/example values.
204+
205+
- path: "usermods/**/library.json"
206+
instructions: >
207+
Scan for secrets and sensitive information in usermod dependency manifests.
208+
209+
Flag any of the following:
210+
- Dependency URLs that embed credentials in the URL itself (e.g., any URL containing credential-bearing userinfo).
211+
- Personal access tokens, OAuth tokens, or API keys as literal strings
212+
anywhere in the file.
213+
- Values matching well-known secret patterns: GitHub PATs (ghp_...,
214+
github_pat_...), AWS access keys (AKIA...), or similarly structured
215+
high-entropy tokens.
216+
217+
Do NOT flag:
218+
- Plain HTTPS or SSH URLs without embedded credentials.
219+
- Version specifiers, semver ranges, or commit SHA references that
220+
contain no credential prefix.
221+
- Repository owner/name path segments (not credential material).
222+
223+
- path: "usermods/**/{readme,README,Readme}.md"
224+
instructions: >
225+
Scan for secrets, passwords, and sensitive information in usermod
226+
documentation files, including inside code blocks, inline code, and prose.
227+
228+
Flag any of the following:
229+
- Hardcoded Wi-Fi SSID or password values that appear to be real (non-placeholder)
230+
strings in configuration or installation examples.
231+
- Hardcoded OTA, AP, or MQTT passwords in code snippets or step-by-step
232+
instructions.
233+
- API keys, bearer tokens, or access tokens shown as literal values.
234+
- Example platformio_override.ini snippets that contain real-looking
235+
credential values instead of placeholders.
236+
- Hardcoded IP addresses combined with credentials in the same example.
237+
238+
Do NOT flag:
239+
- Values that are clearly template placeholders (e.g., YOUR_SSID,
240+
<password>, my_secret, changeme, ****).
241+
- Generic prose describing what a field means without supplying a value.
242+
- Asterisk-masked values (e.g., ******, ••••••).
243+
117244
finishing_touches:
118245
# Docstrings | Options for generating Docstrings for your PRs/MRs.
119246
docstrings:

AGENTS.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ WLED is C++ firmware for ESP32/ESP8266 microcontrollers controlling addressable
44
with a web UI (HTML/JS/CSS). Built with PlatformIO (Arduino framework) and Node.js tooling.
55

66
See also: `.github/copilot-instructions.md`, `.github/agent-build.instructions.md`,
7-
`docs/cpp.instructions.md`, `docs/web.instructions.md`, `docs/cicd.instructions.md`.
7+
`docs/cpp.instructions.md`, `docs/web.instructions.md`, `docs/cicd.instructions.md`,
8+
`docs/hardening.instructions.md`, `docs/securecode.instructions.md`.
89

910
Always reference these instructions - including coding guidelines in `docs/` - first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.
1011

@@ -27,7 +28,7 @@ required C headers for firmware compilation.
2728
Tests use Node.js built-in test runner (`node:test`). The single test file is
2829
`tools/cdata-test.js`. Run it with:
2930

30-
```sh
31+
```bash
3132
npm test # runs all tests via `node --test`
3233
node --test tools/cdata-test.js # run just that file directly
3334
```
@@ -41,7 +42,7 @@ target environments. Always build after code changes: `pio run -e esp32dev`.
4142

4243
### Recovery / Troubleshooting
4344

44-
```sh
45+
```bash
4546
npm run build -- -f # force web UI rebuild
4647
rm -f wled00/html_*.h wled00/js_*.h && npm run build # clean + rebuild UI
4748
pio run --target clean # clean PlatformIO build artifacts
@@ -50,7 +51,7 @@ rm -rf node_modules && npm ci # reinstall Node.js deps
5051

5152
## Project Structure
5253

53-
```
54+
```text
5455
wled00/ # Main firmware source (C++)
5556
data/ # Web UI source (HTML/JS/CSS) — tabs for indentation
5657
html_*.h, js_*.h # Auto-generated (NEVER edit or commit)
@@ -132,6 +133,7 @@ main # Main development trunk (daily/nightly) 17.0.0-dev. Target
132133
- **Performance**: Prefer DRAM (or IRAM) for hot-path data that is *frequently* used. Prefer PSRAM for capacity-oriented buffers where slightly slower access times can be tolerated.
133134

134135
Background Info:
136+
135137
- PSRAM access is up to 18× slower than DRAM on ESP32 (dual-SPI bus), 3–10× slower than DRAM on ESP32-S3/-S2 with quad-SPI bus. On ESP32-S3 with octal PSRAM (`CONFIG_SPIRAM_MODE_OCT`), the penalty is smaller (~2×) because the 8-line DTR bus can transfer 8 bits in parallel. On ESP32-P4 with hex PSRAM (`CONFIG_SPIRAM_MODE_HEX`), the 16-line bus runs at 200 MHz which brings it on-par with DRAM.
136138
- Consider that ESP32 often crashes when the largest DRAM chunk gets below 10 KB.
137139

@@ -158,10 +160,10 @@ Background Info:
158160

159161
#### ESP32 Task Synchronization
160162

161-
* Use FreeRTOS mutexes, semaphores or queues when true concurrent access from multiple FreeRTOS tasks is possible, and race-conditions can lead to unexpected behaviour.
162-
* **Avoid `portENTER_CRITICAL()` / `portEXIT_CRITICAL()`**, as these functions stall the complete system and may cause LEDs flickering. Prefer FreeRTOS mutexes, semaphores or queues.
163-
* **Important**: Not every shared resource needs a mutex. Some synchronization is guaranteed by the overall control flow, for example when function calls are sequenced within the same loop iteration.
164-
* Consider RAII as an alternative to mutexes or semaphores.
163+
- Use FreeRTOS mutexes, semaphores or queues when true concurrent access from multiple FreeRTOS tasks is possible, and race-conditions can lead to unexpected behaviour.
164+
- **Avoid `portENTER_CRITICAL()` / `portEXIT_CRITICAL()`**, as these functions stall the complete system and may cause LEDs flickering. Prefer FreeRTOS mutexes, semaphores or queues.
165+
- **Important**: Not every shared resource needs a mutex. Some synchronization is guaranteed by the overall control flow, for example when function calls are sequenced within the same loop iteration.
166+
- Consider RAII as an alternative to mutexes or semaphores.
165167

166168
## Web UI Code Style (wled00/data/)
167169

@@ -240,9 +242,16 @@ No automated linting is configured. Match existing code style in files you edit.
240242
- Provide references when making analyses or recommendations. Support factual claims with verifiable citations, references or concrete evidence; **never fabricate citations**.
241243
- **Highlight user-visible breaking changes and ripple effects** during reviews. Ask for confirmation that these were introduced intentionally.
242244
245+
### Security Hardening
246+
247+
When writing or reviewing code in `wled00/`, `usermods/`, `wled00/data/`, or `.github/workflows/`,
248+
consult `docs/hardening.instructions.md` (concise checklist) and `docs/securecode.instructions.md` (detailed rules with examples).
249+
These files define WLED's threat model, trust boundary model, and WLED-specific constraints (no TLS baseline, no UDP authentication for protocol-defined
250+
multicast/broadcast, firewall-isolated deployment assumed).
251+
243252
### Attribution for AI-generated code
244253
245-
Using AI-generated code can hide the source of the inspiration / knowledge / sources it used.
254+
Using AI-generated code can hide the source of the inspiration / knowledge / sources it used.
246255
247256
- Document attribution of inspiration / knowledge / sources used in the code, e.g. link to GitHub repositories or other websites describing the principles / algorithms used.
248257
- When a larger block of code is generated by an AI tool, embed it into `// AI: below section was generated by an AI` ... `// AI: end` comments (see Comments section).
@@ -251,5 +260,5 @@ Using AI-generated code can hide the source of the inspiration / knowledge / sou
251260
252261
### Supporting Reviews and Discussions
253262
254-
- **For "is it worth doing?" debates** about proposed reliability, safety, or data-integrity mechanisms (CRC checks, backups, power-loss protection): suggest a software **FMEA** (Failure Mode and Effects Analysis).
263+
- **For "is it worth doing?" debates** about proposed reliability, safety, or data-integrity mechanisms (CRC checks, backups, power-loss protection): suggest a software **FMEA** (Failure Mode and Effects Analysis).
255264
Clarify the main feared events, enumerate failure modes, assess each mitigation's effectiveness per failure mode, note common-cause failures, and rate credibility for the typical WLED use case.

0 commit comments

Comments
 (0)