diff --git a/scripts/cli/commands/artifact/cli_artifact_apply.sh b/scripts/cli/commands/artifact/cli_artifact_apply.sh index c1fc19d..1adde75 100644 --- a/scripts/cli/commands/artifact/cli_artifact_apply.sh +++ b/scripts/cli/commands/artifact/cli_artifact_apply.sh @@ -75,7 +75,7 @@ _artifactRmFile() { # ---------------------------------------------------------------------------- _artifactResolve() { local id="$1" - _ART_INDEX="$(lpFetchIndex)" || { isError "artifact: could not fetch/verify the index."; return 1; } + lpFetchIndexInto _ART_INDEX || { isError "artifact: could not fetch/verify the index."; return 1; } local art; art="$(printf '%s' "$_ART_INDEX" | jq -ce --arg id "$id" '.artifacts[]? | select(.id==$id)' 2>/dev/null)" [[ -n "$art" ]] || { isError "artifact: id '$id' not found in the signed index."; return 1; } @@ -534,7 +534,7 @@ artifactApplyAuto() { local policy="${CFG_HOTFIX_AUTO:-security-breakage}" [[ "$policy" == "off" ]] && { isNotice "Hotfix auto-apply is off (CFG_HOTFIX_AUTO=off)."; return 0; } - local index; index="$(lpFetchIndex)" || { isNotice "artifact apply-auto: no index available."; return 0; } + local index; lpFetchIndexInto index || { isNotice "artifact apply-auto: no index available."; return 0; } if [[ "$LP_INDEX_SIGSTATE" != "verified" ]]; then isNotice "artifact apply-auto: index is unsigned (signing not activated) — not auto-applying."; return 0 fi diff --git a/scripts/cli/commands/artifact/cli_artifact_commands.sh b/scripts/cli/commands/artifact/cli_artifact_commands.sh index 8a23873..40dd035 100644 --- a/scripts/cli/commands/artifact/cli_artifact_commands.sh +++ b/scripts/cli/commands/artifact/cli_artifact_commands.sh @@ -97,7 +97,7 @@ artifactListIndex() isHeader "Artifact index ($(lpReleaseChannel))" local json - if ! json="$(lpFetchIndex)"; then + if ! lpFetchIndexInto json; then isError "Could not fetch or verify the artifact index from $(lpArtifactIndexUrl)." isNotice "Nothing is published yet, or the channel is unreachable. (This is expected before the first index ships.)" return 1 diff --git a/scripts/source/artifacts.sh b/scripts/source/artifacts.sh index c65e007..5034232 100644 --- a/scripts/source/artifacts.sh +++ b/scripts/source/artifacts.sh @@ -108,6 +108,23 @@ lpFetchIndex() { return 0 } +# lpFetchIndexInto [cache_path] — lpFetchIndex run IN THIS SHELL so +# the LP_INDEX_SIGSTATE global actually reaches the caller. A plain +# var="$(lpFetchIndex)" capture strands that assignment in the substitution's +# subshell: the caller then reads the file-scope "" and the apply-path gate +# refuses even a correctly signed index. Any caller that inspects +# LP_INDEX_SIGSTATE after fetching MUST use this wrapper, not $(…). +lpFetchIndexInto() { + local __lpfi_var="$1" __lpfi_tmp __lpfi_rc=0 + __lpfi_tmp="$(mktemp)" + lpFetchIndex "${2:-}" > "$__lpfi_tmp" || __lpfi_rc=$? + if (( __lpfi_rc == 0 )); then + printf -v "$__lpfi_var" '%s' "$(cat "$__lpfi_tmp")" + fi + rm -f "$__lpfi_tmp" + return "$__lpfi_rc" +} + # --- Parsing accessors ------------------------------------------------------- # The trust-critical fields (index_serial / valid_until / signature) are read # jq-free above so the security core has no jq dependency. Enumerating the diff --git a/scripts/source/files/arrays/function_manifest.sh b/scripts/source/files/arrays/function_manifest.sh index c42c36d..7a7dc00 100644 --- a/scripts/source/files/arrays/function_manifest.sh +++ b/scripts/source/files/arrays/function_manifest.sh @@ -596,6 +596,7 @@ declare -gA LP_FN_MAP=( [lpArtifactSerialFile]="source/artifacts.sh" [_lpDownload]="source/fetch.sh" [lpFetchIndex]="source/artifacts.sh" + [lpFetchIndexInto]="source/artifacts.sh" [lpFetchRelease]="source/fetch.sh" [lpFetchSource]="source/fetch.sh" [_lpFetchTool]="source/fetch.sh" @@ -1554,6 +1555,7 @@ declare -gA LP_FN_ROOT=( [lpArtifactSerialFile]="scripts" [_lpDownload]="scripts" [lpFetchIndex]="scripts" + [lpFetchIndexInto]="scripts" [lpFetchRelease]="scripts" [lpFetchSource]="scripts" [_lpFetchTool]="scripts" @@ -2533,6 +2535,7 @@ lpArtifactRecordSerial() { source "${install_scripts_dir}source/artifacts.sh"; l lpArtifactSerialFile() { source "${install_scripts_dir}source/artifacts.sh"; lpArtifactSerialFile "$@"; } _lpDownload() { source "${install_scripts_dir}source/fetch.sh"; _lpDownload "$@"; } lpFetchIndex() { source "${install_scripts_dir}source/artifacts.sh"; lpFetchIndex "$@"; } +lpFetchIndexInto() { source "${install_scripts_dir}source/artifacts.sh"; lpFetchIndexInto "$@"; } lpFetchRelease() { source "${install_scripts_dir}source/fetch.sh"; lpFetchRelease "$@"; } lpFetchSource() { source "${install_scripts_dir}source/fetch.sh"; lpFetchSource "$@"; } _lpFetchTool() { source "${install_scripts_dir}source/fetch.sh"; _lpFetchTool "$@"; } diff --git a/scripts/webui/data/generators/updater/webui_artifact_scan.sh b/scripts/webui/data/generators/updater/webui_artifact_scan.sh index e95200a..84cdc6f 100644 --- a/scripts/webui/data/generators/updater/webui_artifact_scan.sh +++ b/scripts/webui/data/generators/updater/webui_artifact_scan.sh @@ -29,7 +29,7 @@ webuiArtifactScan() { fi local index - if ! index="$(lpFetchIndex)"; then + if ! lpFetchIndexInto index; then isNotice "webuiArtifactScan: no verified index available — keeping the prior file." return 0 fi