Skip to content

Conversation

@pdp2121
Copy link
Collaborator

@pdp2121 pdp2121 commented Nov 17, 2025

High Level Overview of Change

Changes made:

  • Moved all ${{ github.* }}, ${{ inputs.* }}, and ${{ secrets.* }} references from inline usage in bash scripts to the env: block of each step
  • Referenced these values in scripts using Shell-style pattern with double quotes.
  • This prevents script injection because GitHub Actions treats env: values as literal strings (preprocessor-style substitution) rather than executable code, ensuring user-controlled data cannot break out of string context to execute commands.

Context of Change

Semgrep scanning indicated:

Using variable interpolation $... with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".

Similar fix: rippled PR #5822

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (non-breaking change that only restructures code)
  • Tests (You added tests for code that already exists, or your new feature included in this PR)
  • Documentation Updates
  • Release

Did you update HISTORY.md?

  • Yes
  • No, this change does not impact library users

Test Plan

CI releases pass.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 17, 2025

Walkthrough

Refactors the GitHub Actions release workflow to route inputs and context values through explicit environment variables, replace direct GitHub context usages with env-derived references, standardize quoting, expand job dependency wiring, and update messaging/URL templating and validations.

Changes

Cohort / File(s) Summary
GitHub Actions: release workflow
.github/workflows/release.yml
Replaced direct github context and github.event.inputs usages with environment variables (e.g., REF_NAME, PACKAGE_NAME_INPUT, NPMJS_DIST_TAG_INPUT, REPO, RUN_ID, PACKAGE_NAME, PACKAGE_VERSION); derived RELEASE_BRANCH from REF_NAME when git metadata is absent; refactored validations and messages to use envs; standardized double-quoted registry URLs; expanded needs blocks to explicit nested forms; updated artifact/PR/release message templating and many step-level env interpolations; minor formatting/spacing tweaks.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review focus:
    • environment variable propagation across jobs and steps (exporting and consumption)
    • correctness of RELEASE_BRANCH derivation and fallbacks
    • all message and artifact URL interpolations using REPO, RUN_ID, PACKAGE_NAME, PACKAGE_VERSION
    • needs restructuring for correct job ordering and absence of circular dependencies

Possibly related PRs

  • Release pipeline #3039 — Refactors the same .github/workflows/release.yml; likely overlaps in replacing context expressions with env-driven values and workflow wiring.

Poem

🐰 I hopped through YAML, tidy and bright,

Swapped contexts for envs in the night.
Branches and messages now hum in tune,
Artifacts found by a single rune.
Hop — release ready, under the moon.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: moving GitHub context variables to environment variables in CI workflows for security.
Description check ✅ Passed The description covers all key required sections: High Level Overview (changes listed), Context of Change (Semgrep finding, similar reference, rationale explained), Type of Change (Bug fix selected), HISTORY.md (No selected), and Test Plan (CI releases pass).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-command-injection

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
.github/workflows/release.yml (1)

616-616: Minor: Single quotes around env var interpolation in regex are unnecessary.

Line 616 uses:

'${{ env.PACKAGE_VERSION }}'

GitHub Actions substitutes ${{ env.PACKAGE_VERSION }} to its literal value (e.g., "1.0.0") before bash processes this line. The single quotes then enclose the already-substituted string literal, which is redundant. The regex matching still works correctly, but the quoting can be simplified for clarity.

- if [[ "$NPM_DIST_TAG" == "latest" ]] && ! [[ '${{ env.PACKAGE_VERSION }}' =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
-   echo "With npmjs_dist_tag 'latest', version must be of the form x.y.z. Found '${{ env.PACKAGE_VERSION }}'." >&2
+ if [[ "$NPM_DIST_TAG" == "latest" ]] && ! [[ "${{ env.PACKAGE_VERSION }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+   echo "With npmjs_dist_tag 'latest', version must be of the form x.y.z. Found ${{ env.PACKAGE_VERSION }}." >&2
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 37efcc1 and 5b5609c.

📒 Files selected for processing (1)
  • .github/workflows/release.yml (21 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-09-26T21:14:56.813Z
Learnt from: mvadari
Repo: XRPLF/xrpl.js PR: 2788
File: .github/workflows/nodejs.yml:25-25
Timestamp: 2024-09-26T21:14:56.813Z
Learning: In `.github/workflows/nodejs.yml`, the `build-and-lint` job's actions `actions/setup-node` and `actions/cache` are updated to `v4`.

Applied to files:

  • .github/workflows/release.yml
📚 Learning: 2025-10-09T20:16:27.834Z
Learnt from: ckeshava
Repo: XRPLF/xrpl.js PR: 3101
File: .github/workflows/nodejs.yml:220-221
Timestamp: 2025-10-09T20:16:27.834Z
Learning: In `.github/workflows/nodejs.yml`, the `generate-documentation` job intentionally uses `if: startsWith(github.ref, 'refs/tags/xrpl@')` instead of `env.GIT_REF` to ensure documentation is only generated and deployed on actual tag push events, not when the workflow is called via `workflow_call` with a tag reference.

Applied to files:

  • .github/workflows/release.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: unit (22.x)
  • GitHub Check: browser (24.x)
  • GitHub Check: unit (20.x)
  • GitHub Check: integration (22.x)
  • GitHub Check: integration (20.x)
  • GitHub Check: integration (24.x)
  • GitHub Check: unit (24.x)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (8)
.github/workflows/release.yml (8)

32-94: Correctly implements the security pattern for input validation.

Environment variables are properly extracted from GitHub context (lines 33-36) and safely referenced in the run script with single-quoted substitution (lines 41, 50, 74). This prevents command injection even if user-supplied package_name or npmjs_dist_tag contain special characters. The path traversal guards (.., /) and validation regexes provide defense-in-depth.


96-123: Correctly applies the env var pattern to package version retrieval.

Input variables are extracted to env block (lines 98-100) and safely used in the run script (lines 103, 114). The version validation logic correctly ensures latest tag semantics with the x.y.z format check.


179-194: Slack failure notification properly uses env vars for secrets and context.

The SLACK_TOKEN secret (line 182) is never exposed in the run script; the Bearer token is injected directly into the curl header via ${{ env.SLACK_TOKEN }} (line 189), which GitHub Actions substitutes before bash sees it. The repository and run ID are also safely passed through env vars.


212-223: OWASP API upload correctly isolates sensitive context.

The OWASP_TOKEN secret and PACKAGE_VERSION are both set as env vars (lines 213-215) and safely used in the curl command (line 218). No secrets are leaked to logs or error messages.


241-248: Artifact URL construction safely composes values from env vars.

GitHub repository, run ID, and artifact ID are all extracted to env (lines 243-246) and safely interpolated into the artifact download URL. This prevents injection through any of these context values.


263-290: GitHub issue creation properly parameterizes all user-controlled input.

Environment variables for package name, version, branch, and artifact URL are safely passed to the gh CLI. The jq command correctly quoting all variables prevents shell injection when building JSON.


604-621: npm publish step correctly handles dist-tag input.

The NPMJS_DIST_TAG_INPUT is extracted to env (line 606) and safely assigned in the run script (line 612). Validation logic on lines 613–619 (including the regex check) correctly prevents invalid or dangerous dist-tag values.


474-502: Dev team Slack notification correctly parameterizes dynamic message content.

Environment variables for package name, version, repo, run ID, and reviewers are extracted (lines 477–486) and safely composed into the Slack message (lines 489, 491, 493–494). The multi-line bash string construction preserves safety by using env var substitution before the message is passed to jq.

Copy link

@bthomee bthomee left a comment

Choose a reason for hiding this comment

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

Thanks for doing this - it's looking good so far.

if: failure()
env:
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}
PACKAGE_VERSION: ${{ env.PACKAGE_VERSION }}
Copy link

Choose a reason for hiding this comment

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

Here and elsewhere, this environment variable (re)definition shouldn't be necessary as it's already an env var.

Copy link
Collaborator Author

@pdp2121 pdp2121 Nov 17, 2025

Choose a reason for hiding this comment

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

Great catch! I removed redundant redefinition here: 9b731b7

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/release.yml (1)

360-360: Minor inconsistency in shell variable quoting style.

Line 360 uses $REPO and $RUN_ID without braces, whereas the codebase generally follows the ${VAR} pattern (e.g., lines 474, 533, 647, 664) per the recommendation in past reviews to avoid string concatenation pitfalls. While functionally correct in this context (jq --arg receives the unquoted expansion), consider using ${REPO} and ${RUN_ID} for consistency.

-              --arg body  "Automated PR for release **$VERSION** from **$RELEASE_BRANCH** → **main**. Workflow Run: https://github.com/$REPO/actions/runs/$RUN_ID" \
+              --arg body  "Automated PR for release **${VERSION}** from **${RELEASE_BRANCH}** → **main**. Workflow Run: https://github.com/${REPO}/actions/runs/${RUN_ID}" \
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b5609c and f6ae21a.

📒 Files selected for processing (1)
  • .github/workflows/release.yml (14 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: mvadari
Repo: XRPLF/xrpl.js PR: 2788
File: .github/workflows/nodejs.yml:25-25
Timestamp: 2024-09-26T21:14:56.813Z
Learning: In `.github/workflows/nodejs.yml`, the `build-and-lint` job's actions `actions/setup-node` and `actions/cache` are updated to `v4`.
Learnt from: ckeshava
Repo: XRPLF/xrpl.js PR: 3101
File: .github/workflows/nodejs.yml:220-221
Timestamp: 2025-10-09T20:16:27.834Z
Learning: In `.github/workflows/nodejs.yml`, the `generate-documentation` job intentionally uses `if: startsWith(github.ref, 'refs/tags/xrpl@')` instead of `env.GIT_REF` to ensure documentation is only generated and deployed on actual tag push events, not when the workflow is called via `workflow_call` with a tag reference.
📚 Learning: 2024-09-26T21:14:56.813Z
Learnt from: mvadari
Repo: XRPLF/xrpl.js PR: 2788
File: .github/workflows/nodejs.yml:25-25
Timestamp: 2024-09-26T21:14:56.813Z
Learning: In `.github/workflows/nodejs.yml`, the `build-and-lint` job's actions `actions/setup-node` and `actions/cache` are updated to `v4`.

Applied to files:

  • .github/workflows/release.yml
📚 Learning: 2025-10-09T20:16:27.834Z
Learnt from: ckeshava
Repo: XRPLF/xrpl.js PR: 3101
File: .github/workflows/nodejs.yml:220-221
Timestamp: 2025-10-09T20:16:27.834Z
Learning: In `.github/workflows/nodejs.yml`, the `generate-documentation` job intentionally uses `if: startsWith(github.ref, 'refs/tags/xrpl@')` instead of `env.GIT_REF` to ensure documentation is only generated and deployed on actual tag push events, not when the workflow is called via `workflow_call` with a tag reference.

Applied to files:

  • .github/workflows/release.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: integration (24.x)
  • GitHub Check: unit (22.x)
  • GitHub Check: browser (24.x)
  • GitHub Check: unit (24.x)
  • GitHub Check: integration (22.x)
  • GitHub Check: integration (20.x)
  • GitHub Check: unit (20.x)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (1)
.github/workflows/release.yml (1)

32-123: Security refactoring for command injection mitigation is well-executed.

The changes correctly move ${{ github.event.inputs.* }} and other free-form CI inputs into explicit env: blocks at the step level, then reference them via shell-style ${VAR} expansion in run: scripts. This follows the established pattern from rippled PR #5822 and prevents user-controlled data from being evaluated as shell code. All validation logic properly uses these environment variables without direct GitHub context interpolation. The approach is sound and comprehensive across the affected steps.

SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}
CHANNEL: "#ripplex-security"
EXECUTOR: ${{ github.triggering_actor || github.actor }}
PACKAGE_NAME: ${{ needs.get_version.outputs.package_version && github.event.inputs.package_name }}
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 17, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Questionable logic for PACKAGE_NAME assignment in ask_for_sec_team_review job.

The expression ${{ needs.get_version.outputs.package_version && github.event.inputs.package_name }} will coerce PACKAGE_NAME to the boolean false if the version is empty, rather than being unset or defaulting to a safe fallback. This appears inconsistent with line 527 (PACKAGE_VERSION assignment) and could produce misleading output in Slack messages (line 535) that interpolate PACKAGE_NAME.

Simplify to:

-          PACKAGE_NAME: ${{ needs.get_version.outputs.package_version && github.event.inputs.package_name }}
+          PACKAGE_NAME: ${{ github.event.inputs.package_name }}

Unless there is a specific requirement to conditionally omit PACKAGE_NAME, in which case clarify the intent with a comment.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
PACKAGE_NAME: ${{ needs.get_version.outputs.package_version && github.event.inputs.package_name }}
PACKAGE_NAME: ${{ github.event.inputs.package_name }}
🤖 Prompt for AI Agents
In .github/workflows/release.yml around line 526, the PACKAGE_NAME assignment
uses a logical-and expression that will produce a boolean false when
package_version is empty; replace this with an explicit, safer assignment so
PACKAGE_NAME is either the provided input or an empty/default value (use an
explicit conditional comparison against package_version rather than relying on
&&), and add a short comment if the intent is to omit PACKAGE_NAME when no
version exists.

Copy link

Choose a reason for hiding this comment

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

This seems a bit questionable indeed.

I think - after making the fix I proposed in another comment - that using {{ needs.get_version.outputs.package_version }} should be enough, since now the value will get correctly set.

If the output isn't always set (or can be empty), then you are more likely to want to use || here than &&. However, in that case you will want to apply the same login in other places too, e.g. when running the faucet test.

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for other uses of && or || in GitHub Actions expressions in the release.yml file
rg -n '\$\{\{.*(\&\&|\|\|).*\}\}' .github/workflows/release.yml

Length of output: 617


#!/bin/bash
# Check how PACKAGE_NAME is set in other jobs in the release.yml file
rg -n 'PACKAGE_NAME:.*\$\{\{' .github/workflows/release.yml

🧠 Learnings used
Learnt from: mvadari
Repo: XRPLF/xrpl.js PR: 2788
File: .github/workflows/nodejs.yml:25-25
Timestamp: 2024-09-26T21:14:56.813Z
Learning: In `.github/workflows/nodejs.yml`, the `build-and-lint` job's actions `actions/setup-node` and `actions/cache` are updated to `v4`.

@pdp2121 pdp2121 requested a review from bthomee November 17, 2025 22:49
Copy link
Collaborator

@shichengripple001 shichengripple001 left a comment

Choose a reason for hiding this comment

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

LGTM

@kuan121 kuan121 mentioned this pull request Nov 18, 2025
9 tasks
@pdp2121 pdp2121 enabled auto-merge (squash) November 18, 2025 16:28
@pdp2121 pdp2121 disabled auto-merge November 18, 2025 16:28
- Move all ${{ github.* }} and ${{ inputs.* }} from run: scripts to env: blocks
- Use Shell-style ${VAR} pattern in run: blocks for better readability
- Remove redundant env redefinitions
- Follows rippled PR #5822 best practices
@pdp2121 pdp2121 force-pushed the fix-command-injection branch from f6ae21a to 89c3a8d Compare November 18, 2025 16:34
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
.github/workflows/release.yml (1)

526-526: Fix the logical-AND expression that produces string false when version is empty.

The PACKAGE_NAME assignment uses ${{ needs.get_version.outputs.package_version && github.event.inputs.package_name }}, which evaluates to the string literal false if the version is empty, rather than defaulting to the input value. This causes downstream Slack messages (line 535) to interpolate false as the package name.

Apply this diff:

-          PACKAGE_NAME: ${{ needs.get_version.outputs.package_version && github.event.inputs.package_name }}
+          PACKAGE_NAME: ${{ github.event.inputs.package_name }}
🧹 Nitpick comments (1)
.github/workflows/release.yml (1)

355-361: Standardize shell variable syntax to use ${VAR} consistently.

Lines 357 and 360 use inconsistent shell variable syntax ($VAR without braces) while the rest of the workflow uses ${VAR}. Per prior guidance in this codebase, ${VAR} is preferred to avoid string-concatenation pitfalls and for consistency.

Apply this diff:

             CREATE_JSON="$(jq -n \
-              --arg title "Release $VERSION: $RELEASE_BRANCH → main" \
+              --arg title "Release ${VERSION}: ${RELEASE_BRANCH} → main" \
               --arg head  "$RELEASE_BRANCH" \
-              --arg base  "main" \
-              --arg body  "Automated PR for release **$VERSION** from **$RELEASE_BRANCH** → **main**. Workflow Run: https://github.com/$REPO/actions/runs/$RUN_ID" \
+              --arg base  "main" \
+              --arg body  "Automated PR for release **${VERSION}** from **${RELEASE_BRANCH}** → **main**. Workflow Run: https://github.com/${REPO}/actions/runs/${RUN_ID}" \
               '{title:$title, head:$head, base:$base, body:$body}')"
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f6ae21a and 89c3a8d.

📒 Files selected for processing (1)
  • .github/workflows/release.yml (14 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: mvadari
Repo: XRPLF/xrpl.js PR: 2788
File: .github/workflows/nodejs.yml:25-25
Timestamp: 2024-09-26T21:14:56.813Z
Learning: In `.github/workflows/nodejs.yml`, the `build-and-lint` job's actions `actions/setup-node` and `actions/cache` are updated to `v4`.
📚 Learning: 2024-09-26T21:14:56.813Z
Learnt from: mvadari
Repo: XRPLF/xrpl.js PR: 2788
File: .github/workflows/nodejs.yml:25-25
Timestamp: 2024-09-26T21:14:56.813Z
Learning: In `.github/workflows/nodejs.yml`, the `build-and-lint` job's actions `actions/setup-node` and `actions/cache` are updated to `v4`.

Applied to files:

  • .github/workflows/release.yml
📚 Learning: 2025-10-09T20:16:27.834Z
Learnt from: ckeshava
Repo: XRPLF/xrpl.js PR: 3101
File: .github/workflows/nodejs.yml:220-221
Timestamp: 2025-10-09T20:16:27.834Z
Learning: In `.github/workflows/nodejs.yml`, the `generate-documentation` job intentionally uses `if: startsWith(github.ref, 'refs/tags/xrpl@')` instead of `env.GIT_REF` to ensure documentation is only generated and deployed on actual tag push events, not when the workflow is called via `workflow_call` with a tag reference.

Applied to files:

  • .github/workflows/release.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: browser (24.x)
  • GitHub Check: integration (22.x)
  • GitHub Check: unit (22.x)
  • GitHub Check: integration (20.x)
  • GitHub Check: integration (24.x)
  • GitHub Check: unit (24.x)
  • GitHub Check: unit (20.x)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (6)
.github/workflows/release.yml (6)

32-122: Validate inputs and version retrieval steps are secure and well-structured.

The refactoring properly isolates inputs into environment variables (lines 33–36, 98–100) and all downstream references use safe shell syntax with proper quoting. The validation logic correctly rejects path traversal and version-tag confusion. The fallback to ${REF_NAME} when git branch info is unavailable (lines 40–42) is appropriate.


145-303: Pre-release job properly uses environment variables for Slack, OWASP, and artifact operations.

The transition of SLACK_TOKEN, OWASP_TOKEN, REPO, RUN_ID, and other sensitive values to env: blocks is correct. Artifact URLs are safely constructed using ${VAR} interpolation within jq --arg calls (line 246). Issue creation properly quotes the title and body with environment variables (line 286).


325-387: PR creation and reviewer fetching steps safely parameterize GitHub API calls.

The ensure_pr step properly passes GitHub context through environment variables (lines 333–338) and uses jq -n --arg to safely construct the API payload (lines 356–361). The fetch_reviewers function correctly retrieves environment configuration from the GitHub API using bearer-token authentication (lines 393–415).


425-487: Slack messaging steps use safe environment-variable interpolation.

The release summary and dev-team notification steps correctly interpolate artifact IDs, branch names, and repository URLs via environment variables. The MSG construction on line 481 uses printf '%b' to safely handle multi-line content. All HTTP headers and request bodies are safely built with jq and shell variables.


589-605: npm publishing step correctly isolates dist-tag input and applies version validation.

The NPMJS_DIST_TAG_INPUT environment variable is safely referenced to build the effective tag (line 596). The fallback to "latest" and the semver-format check for latest releases (lines 600–603) prevent invalid release states.


607-624: Git tagging step safely constructs tag name from environment variables.

Line 611 uses ${PACKAGE_NAME} and ${PACKAGE_VERSION} with the @ separator, which are validated inputs that have already undergone regex checks (e.g., line 51). The existence check and push are guarded appropriately.

@pdp2121 pdp2121 force-pushed the fix-command-injection branch from 89c3a8d to ab163e8 Compare November 18, 2025 16:49
- name: Validate inputs
env:
REF_NAME: ${{ github.ref_name }}
PACKAGE_NAME_INPUT: ${{ github.event.inputs.package_name }}
Copy link

Choose a reason for hiding this comment

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

Some optional feedback, which is easy to fix but not a blocker in any way:

  • In env: you now have PACKAGE_NAME_INPUT: ${{ github.event.inputs.package_name }}.
  • In run: you then do PKG_NAME="${PACKAGE_NAME_INPUT}".

You can easily combine this by:

  • In env: do PKG_NAME: ${{ github.event.inputs.package_name }}.
  • In run: remove the assignment statement. The PKG_NAME can be used directly in the script.

Separately, I noticed you sometimes refer to PACKAGE_XXX and sometimes to PKG_XXX for some XXX. You could consider doing a find-and-replace to make them all consistent. I'd suggest replacing all occurrences of PACKAGE by PKG since it's shorter and its meaning is clear.

env:
REF_NAME: ${{ github.ref_name }}
PACKAGE_NAME_INPUT: ${{ github.event.inputs.package_name }}
NPMJS_DIST_TAG_INPUT: ${{ github.event.inputs.npmjs_dist_tag }}
Copy link

Choose a reason for hiding this comment

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

The same applies to this one, where you define NPMJS_DIST_TAG_INPUT here and then in the code you assign it to NPM_DIST_TAG; you may as well use NPM_DIST_TAG here directly.

run: |
curl -X POST \
-H "X-Api-Key: ${{ secrets.OWASP_TOKEN }}" \
-H "X-Api-Key: ${OWASP_TOKEN}" \
Copy link

Choose a reason for hiding this comment

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

FWIW I believe it's not a concern to directly reference secrets via ${{ secrets.XXX }} in a run: statement, since end users cannot manipulate them (unlike the GitHub object, according to Semgrep).

Either way, assigning it to an env var is perfectly fine, so you can leave this change as -is.

fi
echo "PACKAGE_VERSION=$VERSION" >> "$GITHUB_ENV"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "PACKAGE_VERSION=${VERSION}" >> "$GITHUB_ENV"
Copy link

Choose a reason for hiding this comment

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

Suggested change
echo "PACKAGE_VERSION=${VERSION}" >> "$GITHUB_ENV"
echo "package_version=${VERSION}" >> "$GITHUB_OUTPUT"

In follow-up jobs you refer to ${{ needs.get_version.outputs.package_version }} but that will always be empty, since you're writing the version as an env var and not as an output.

SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}
CHANNEL: "#ripplex-security"
EXECUTOR: ${{ github.triggering_actor || github.actor }}
PACKAGE_NAME: ${{ needs.get_version.outputs.package_version && github.event.inputs.package_name }}
Copy link

Choose a reason for hiding this comment

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

This seems a bit questionable indeed.

I think - after making the fix I proposed in another comment - that using {{ needs.get_version.outputs.package_version }} should be enough, since now the value will get correctly set.

If the output isn't always set (or can be empty), then you are more likely to want to use || here than &&. However, in that case you will want to apply the same login in other places too, e.g. when running the faucet test.

@pdp2121 pdp2121 merged commit 8abcf5a into main Nov 18, 2025
11 checks passed
@pdp2121 pdp2121 deleted the fix-command-injection branch November 18, 2025 16:58
pdp2121 added a commit that referenced this pull request Nov 21, 2025
Address some outstanding comments in #3133.
Changes include:

Use env variable names PKG_NAME, PKG_VERSION, and NPM_DIST_TAG consistently within the script and remove unnecessary intermediate variables.
Write package version in line https://github.com/XRPLF/xrpl.js/blob/main/.github/workflows/release.yml#L122 into $GITHUB_OUTPUT instead of $GITHUB_ENV to be used in other jobs (instead of the same job).
Fix line https://github.com/XRPLF/xrpl.js/blob/main/.github/workflows/release.yml#L526 to just use ${{ needs.get_version.outputs.package_name }} directly since this should be available and && operator does not make much sense in this context.
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.

5 participants