fix: security and quality audit — 21 findings addressed#376
fix: security and quality audit — 21 findings addressed#376
Conversation
Address 21 findings from codebase audit: - SEC-01: Move setup key from CLI arg to NB_SETUP_KEY env var - SEC-02/CI-04: Fix GitHub Actions expression injection vectors - SEC-03: Pin home-assistant/actions to commit SHA - AA-03: Add /sbin/ to AppArmor for iptables execution - SEC-05/06: Validate URLs, enforce NB_ prefix for env vars - SEC-07: Pin Docker image by digest - CQ-01/02/03: Error handling, atomic resolv.conf, exec for signals - AA-04/05/06/07: AppArmor path and network rule gaps - CI-01/03/05: Replace archived action, add permissions, fix patterns Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR implements a broad security/quality audit remediation for the NetBird Home Assistant add-on, focusing on secret handling, CI hardening, and runtime reliability/AppArmor compatibility.
Changes:
- Hardens the add-on startup script (safer config migration, secret handling via
NB_SETUP_KEY, redacted env var logging, atomicresolv.confupdate, andexecfor proper signal handling). - Strengthens supply-chain/CI security (pins helper actions to a SHA, adds explicit job permissions, replaces archived changed-files action usage with
git diff, and reduces expression-injection exposure viaenv:). - Adds an AppArmor profile and pins the upstream NetBird image by digest.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
netbird/rootfs/etc/s6-overlay/s6-rc.d/netbird/run |
Improves startup security/reliability (setup key handling, env var validation/redaction, atomic resolv.conf update, exec). |
netbird/rootfs/etc/s6-overlay/s6-rc.d/netbird/finish |
Removes dead code in the finish handler. |
netbird/Dockerfile |
Pins NetBird base image by digest for supply-chain integrity. |
netbird/config.yaml |
Tightens schema validation for URLs/hostname and restricts env vars to NB_ prefix. |
netbird/apparmor.txt |
Introduces an AppArmor profile with broader execution/path/network permissions needed for the add-on. |
docs/reviews/CODEBASE_REVIEW_2026_04_11.md |
Adds the audit report documenting findings and remediations. |
.github/workflows/update-changelog.yaml |
Moves interpolated values into env: to reduce injection risk and improves robustness. |
.github/workflows/lint.yaml |
Adds explicit permissions and pins helper action to a SHA. |
.github/workflows/builder.yaml |
Adds explicit permissions, pins helper actions, uses git diff for changed files, and avoids direct ${{ }} interpolation in bash logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| bashio::log.info "Setup Key configured (hidden for security)" | ||
| options+=(--setup-key "${setup_key}") | ||
| export NB_SETUP_KEY="${setup_key}" | ||
| fi |
There was a problem hiding this comment.
Fixed: Added null check to setup_key (matching the existing log_level pattern on line 82). Now checks [ "${setup_key}" = "" ] || [ "${setup_key}" = "null" ].
| admin_url: url? | ||
| management_url: url? | ||
| setup_key: str? | ||
| hostname: match(^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?$)? |
There was a problem hiding this comment.
Fixed: Added null checks to admin_url and management_url. Both now check for both empty string and "null" literal, consistent with how log_level is handled.
| env_vars: | ||
| - name: match(^[A-Z_][A-Z0-9_]*$) | ||
| - name: match(^NB_[A-Z0-9_]+$) | ||
| value: str |
There was a problem hiding this comment.
Fixed: Updated DOCS.md env_vars section to document the NB_ prefix requirement and explain the restriction.
| if ! grep -q '# systemd-resolved' /etc/resolv.conf 2>/dev/null; then | ||
| RESOLV_TMP=$(mktemp /tmp/resolv.conf.XXXXXX) | ||
| if { printf '# systemd-resolved\n'; cat /etc/resolv.conf; } > "${RESOLV_TMP}" \ | ||
| && mv -f "${RESOLV_TMP}" /etc/resolv.conf; then | ||
| bashio::log.debug "Prepended systemd-resolved marker to /etc/resolv.conf" | ||
| else | ||
| bashio::log.error "Failed to update /etc/resolv.conf for systemd-resolved workaround" | ||
| rm -f "${RESOLV_TMP}" 2>/dev/null |
There was a problem hiding this comment.
Fixed: Added mktemp failure guard. If mktemp fails, RESOLV_TMP is set to empty and the inner block is skipped with an error log.
- Add null checks for optional config fields (setup_key, admin_url, management_url, hostname) matching existing log_level pattern - Guard mktemp failure in resolv.conf workaround - Document NB_ prefix requirement for env_vars in DOCS.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Key Changes
NB_SETUP_KEYenv var; expression injection vectors fixed withenv:blocks; actions pinned to SHAf6f29a7; Docker image pinned by digestexec netbird upfor proper S6 signal delivery/sbin/**for iptables,/config/**for state files,network inet rawfor ICMP,network unix streamfor daemon socketjitterbit/get-changed-fileswith native git diff; explicit permissions on all jobsurl?type; hostname regex enforced; env_vars requireNB_prefix (breaking change)Breaking Changes
env_varsname regex changed from^[A-Z_][A-Z0-9_]*$to^NB_[A-Z0-9_]+$— users with non-NB_prefixed variables must rename themNot Fixed (2 findings)
Test Plan
shellcheckpasses onrunscript (clean)shellcheckonfinishscript shows only pre-existing warningsFull audit report:
docs/reviews/CODEBASE_REVIEW_2026_04_11.mdGenerated with Claude Code