Skip to content

(#9400 P1b) Replace unsafe eval with declare -g and nameref#9461

Open
iav wants to merge 4 commits intomainfrom
fix/p1b-eval-to-declare
Open

(#9400 P1b) Replace unsafe eval with declare -g and nameref#9461
iav wants to merge 4 commits intomainfrom
fix/p1b-eval-to-declare

Conversation

@iav
Copy link
Copy Markdown
Contributor

@iav iav commented Mar 2, 2026

Summary

Replaces 5 eval usages that can be trivially eliminated — part of the bash safety plan in #9400 (P1b).

File Old New
lib/functions/cli/utils-cli.sh eval "declare -g $name=\"$value\"" declare -g "${name}=${value}"
lib/functions/configuration/interactive.sh eval "$1"='$2' declare -g "${1}=${2}"
lib/functions/configuration/interactive.sh eval "ARMBIAN_INTERACTIVE_CONFIGS[${1}]"='$2' ARMBIAN_INTERACTIVE_CONFIGS["${1}"]="${2}"
lib/functions/configuration/change-tracking.sh eval "var_value=\"\${${var_name}[@]}\"" local -n nameref
lib/functions/artifacts/artifacts-obtain.sh eval "declare ${var}_ARRAY=\"\${${var}[*]}\"" local -n nameref

Why eval is risky here

eval executes its argument as shell code. If a variable name or value were ever a crafted string (e.g. from user input or a config file), it could inject arbitrary commands. The bash builtins used as replacements do not have this property.

Note: parse_cmdline_params already validates parameter names against ^[a-zA-Z_][a-zA-Z0-9_]*$ before inserting into ARMBIAN_PARSED_CMDLINE_PARAMS, so names reaching apply_cmdline_params_to_env are guaranteed to be valid identifiers — closing the array-index injection vector at the source.

The nameref case explained

change-tracking.sh and artifacts-obtain.sh both needed to read an array variable whose name is stored in a scalar at runtime. The original comment in change-tracking said # sorry. The fix uses bash 4.3+ nameref (local -n), which creates an alias to the variable without executing any code:

# Before — eval reads array by dynamic name, code-injection risk:
eval "var_value=\"\${${var_name}[@]}\"" # sorry

# After — nameref creates a safe alias, no code executed:
local -n _ct_arr_ref="${var_name}"  # alias for the array named in $var_name
var_value="${_ct_arr_ref[*]}"       # read through the alias
unset -n _ct_arr_ref                # remove alias only (not the array!) to avoid
                                    # "already a nameref" warnings next iteration

Out of scope

Other eval usages in lib/ intentionally left alone:

  • cli-configdump.sh:61 — deserializer for @Q-quoted serialization (safe by construction, cannot be trivially replaced without reworking serialization).
  • Code/hook materialization (extensions.sh, armbian-bsp-desktop-deb.sh, traps.sh, heredocs in utils-cli.sh) — legitimate dynamic code generation.
  • eval env "${COMPILER}gcc" in compilation paths — redundant eval but no injection risk; not in P1b scope.

Test plan

  • shellcheck passes with no new warnings
  • compile.sh runs normally (cmdline param application, interactive config, change tracking, artifact config dump all exercised in normal builds)

🤖 Generated with Claude Code

@iav iav requested a review from a team as a code owner March 2, 2026 01:00
@iav iav requested review from catalinii and igorpecovnik and removed request for a team March 2, 2026 01:00
@github-actions github-actions bot added size/small PR with less then 50 lines 05 Milestone: Second quarter release labels Mar 2, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 2, 2026

📝 Walkthrough

Walkthrough

These changes replace unsafe eval-based dynamic variable assignments with safer bash mechanisms across three shell script utility files, maintaining functional behavior while improving security and code safety.

Changes

Cohort / File(s) Summary
Shell Script Security Hardening
lib/functions/cli/utils-cli.sh
Replaces eval with direct declare -g syntax for global variable assignment from cmdline parameters.
Array Variable Extraction
lib/functions/configuration/change-tracking.sh
Replaces eval-based array value extraction with bash nameref approach for safer variable aliasing.
Interactive Configuration
lib/functions/configuration/interactive.sh
Replaces eval-based assignment with declare -g combined with direct associative array updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A hop through bash, away from eval's peril,
Where nameref and declare now bravely stir!
No more dancing quotes in dangerous ways,
Our scripts are safer through these careful days! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main changes: replacing unsafe eval calls with safer alternatives (declare -g and nameref) across multiple shell script files.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/p1b-eval-to-declare

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.

@github-actions github-actions bot added Needs review Seeking for review Framework Framework components labels Mar 2, 2026
@iav
Copy link
Copy Markdown
Contributor Author

iav commented Mar 2, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 2, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.


# if the var is an array...
if [[ "${array_values:-"no"}" == "yes" ]]; then
eval "var_value=\"\${${var_name}[@]}\"" # sorry
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The comment tells me that Ricardo put some thought into this before leaving as it is. So I'd like to hear his opinion on the change.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

iav and others added 4 commits April 16, 2026 22:30
eval "declare -g $name=\"$value\"" is equivalent to the safer
declare -g "${name}=${value}" which avoids code injection risk.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two eval calls in set_interactive_config_value():
- eval "$1"='$2' → declare -g "${1}=${2}"
- eval "ARMBIAN_INTERACTIVE_CONFIGS[${1}]"='$2' → direct array assignment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The original code used eval to read an array variable with a dynamic name:

    eval "var_value=\"\${${var_name}[@]}\"" # sorry

eval works, but it executes arbitrary code — if $var_name were ever a
crafted string, it could inject commands.

bash 4.3+ nameref (local -n) creates an alias to the variable named in
$var_name without executing any code:

    local -n _ct_arr_ref="${var_name}"
    var_value="${_ct_arr_ref[*]}"
    unset -n _ct_arr_ref

unset -n removes only the alias (not the referenced array), preventing
"already a nameref" warnings on subsequent loop iterations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@iav iav force-pushed the fix/p1b-eval-to-declare branch from a4e2d2c to 17f8209 Compare April 16, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

05 Milestone: Second quarter release Framework Framework components Needs review Seeking for review size/small PR with less then 50 lines

Development

Successfully merging this pull request may close these issues.

3 participants