Skip to content

[WIP] Automate generation of weekly CSV reports for Canton wallets#111

Closed
Copilot wants to merge 2 commits intomainfrom
copilot/automate-weekly-csv-reports-ang-812
Closed

[WIP] Automate generation of weekly CSV reports for Canton wallets#111
Copilot wants to merge 2 commits intomainfrom
copilot/automate-weekly-csv-reports-ang-812

Conversation

Copy link

Copilot AI commented Jan 27, 2026

Plan for Automating Weekly Canton Wallet CSV Reports (ANG-812)

  • Create Python script to fetch Canton wallet transaction data from Cantonscan API
    • Support for validator wallet: nethermind-angkor-1::12201d94ec4ba973ab5c51e3b769a6aca54f061afc963619a4d6109044eaccafc7ba
    • Support for non-validator (Nethermind) wallet: nethermind::1220409a9fcc5ff6422e29ab978c22c004dde33202546b4bcbde24b25b85353366c2
    • Generate CSV reports with transfers and summary data
    • Mock data support for testing and API fallback
  • Create reusable GitHub Actions workflow for Canton reports
    • Schedule: Weekly execution using cron
    • Run Python script to generate reports
    • Upload CSV reports as workflow artifacts
  • Add example workflow showing how to use the Canton reports workflow
  • Update documentation (README) with Canton reports workflow info
  • Test the workflow to ensure it works correctly
  • Run code review and security checks

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@linear
Copy link

linear bot commented Jan 27, 2026

Copilot AI requested a review from derrix060 January 27, 2026 09:53
Copilot stopped work on behalf of derrix060 due to an error January 27, 2026 09:53

- name: Generate Canton wallet reports
run: |
mkdir -p ${{ inputs.output_dir }}

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.output_dir }
, which may be controlled by an external user.

Copilot Autofix

AI 9 days ago

In general, to fix this class of problem, any untrusted GitHub Actions input must not be interpolated directly into shell commands via ${{ ... }} inside a run: block. Instead, assign it to an environment variable at the step level using expression syntax, and then reference it using the shell’s native variable expansion ($VAR), avoiding unquoted command construction where possible.

For this workflow, the best fix is:

  • Add an env: section on the “Generate Canton wallet reports” step that maps:
    • OUTPUT_DIR: ${{ inputs.output_dir }}
    • USE_MOCK_DATA: ${{ inputs.use_mock_data }}
    • VALIDATOR_ONLY: ${{ inputs.validator_only }}
    • NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
    • DAYS: ${{ inputs.days }}
  • In the shell script:
    • Replace mkdir -p ${{ inputs.output_dir }} with mkdir -p "$OUTPUT_DIR".
    • Initialize ARGS="--output-dir \"$OUTPUT_DIR\"" so the directory is properly quoted.
    • Replace all ${{ inputs.* }} conditions with checks against the corresponding env vars ($USE_MOCK_DATA, etc.).
    • Replace ARGS="$ARGS --days ${{ inputs.days }}" with ARGS="$ARGS --days $DAYS".
    • Finally, run the Python script with safe argument passing: python3 scripts/generate_canton_reports.py $ARGS. Because we’re constructing a single string, to fully avoid word-splitting issues you could instead build an array, but that would be a larger functional change. Given the existing pattern, ensuring that only trusted or simple values are interpolated and that paths are quoted keeps behavior while addressing the injection vector from ${{ ... }}.

We must also fix later uses of ${{ inputs.output_dir }} in other steps’ run: sections by moving the value into an env var and using $OUTPUT_DIR instead. The upload-artifact with.path is not executed as shell, so it may remain unchanged, but keeping it consistent by using an env var is still safe; however, to minimize changes we will only adjust the run: blocks.

All required changes are confined to .github/workflows/canton-reports.yaml in the shown step definitions; no new methods or external dependencies are needed.

Suggested changeset 1
.github/workflows/canton-reports.yaml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/canton-reports.yaml b/.github/workflows/canton-reports.yaml
--- a/.github/workflows/canton-reports.yaml
+++ b/.github/workflows/canton-reports.yaml
@@ -49,31 +49,40 @@
           python-version: '3.11'
           
       - name: Generate Canton wallet reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
+          USE_MOCK_DATA: ${{ inputs.use_mock_data }}
+          VALIDATOR_ONLY: ${{ inputs.validator_only }}
+          NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
+          DAYS: ${{ inputs.days }}
         run: |
-          mkdir -p ${{ inputs.output_dir }}
+          mkdir -p "$OUTPUT_DIR"
           
-          ARGS="--output-dir ${{ inputs.output_dir }}"
+          ARGS="--output-dir \"$OUTPUT_DIR\""
           
-          if [ "${{ inputs.use_mock_data }}" == "true" ]; then
+          if [ "$USE_MOCK_DATA" = "true" ]; then
             ARGS="$ARGS --mock"
           fi
           
-          if [ "${{ inputs.validator_only }}" == "true" ]; then
+          if [ "$VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --validator-only"
           fi
           
-          if [ "${{ inputs.non_validator_only }}" == "true" ]; then
+          if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --non-validator-only"
           fi
           
-          ARGS="$ARGS --days ${{ inputs.days }}"
+          ARGS="$ARGS --days $DAYS"
           
+          # shellcheck disable=SC2086
           python3 scripts/generate_canton_reports.py $ARGS
           
       - name: List generated reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
         run: |
           echo "Generated reports:"
-          ls -lh ${{ inputs.output_dir }}
+          ls -lh "$OUTPUT_DIR"
           
       - name: Upload reports as artifacts
         uses: actions/upload-artifact@v4
EOF
@@ -49,31 +49,40 @@
python-version: '3.11'

- name: Generate Canton wallet reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
USE_MOCK_DATA: ${{ inputs.use_mock_data }}
VALIDATOR_ONLY: ${{ inputs.validator_only }}
NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
DAYS: ${{ inputs.days }}
run: |
mkdir -p ${{ inputs.output_dir }}
mkdir -p "$OUTPUT_DIR"

ARGS="--output-dir ${{ inputs.output_dir }}"
ARGS="--output-dir \"$OUTPUT_DIR\""

if [ "${{ inputs.use_mock_data }}" == "true" ]; then
if [ "$USE_MOCK_DATA" = "true" ]; then
ARGS="$ARGS --mock"
fi

if [ "${{ inputs.validator_only }}" == "true" ]; then
if [ "$VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --validator-only"
fi

if [ "${{ inputs.non_validator_only }}" == "true" ]; then
if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --non-validator-only"
fi

ARGS="$ARGS --days ${{ inputs.days }}"
ARGS="$ARGS --days $DAYS"

# shellcheck disable=SC2086
python3 scripts/generate_canton_reports.py $ARGS

- name: List generated reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
run: |
echo "Generated reports:"
ls -lh ${{ inputs.output_dir }}
ls -lh "$OUTPUT_DIR"

- name: Upload reports as artifacts
uses: actions/upload-artifact@v4
Copilot is powered by AI and may make mistakes. Always verify output.
run: |
mkdir -p ${{ inputs.output_dir }}

ARGS="--output-dir ${{ inputs.output_dir }}"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.output_dir }
, which may be controlled by an external user.

Copilot Autofix

AI 9 days ago

In general, to fix this kind of issue in GitHub Actions, you should stop interpolating untrusted inputs directly into run: commands using ${{ ... }} and instead: (1) assign the expression value to an environment variable using env: or env on the step, and (2) reference that environment variable using the shell’s native variable syntax ("$VAR"). This way the shell receives the value as a single argument and does not re-interpret any embedded metacharacters as additional commands.

For this specific workflow, we should:

  • Pass inputs.output_dir and inputs.days into the step via environment variables, e.g. OUTPUT_DIR: ${{ inputs.output_dir }} and DAYS: ${{ inputs.days }}.
  • In the run: script, replace ${{ inputs.output_dir }} and ${{ inputs.days }} with $OUTPUT_DIR and $DAYS.
  • Build ARGS using those shell variables so the script never sees GitHub expression syntax inside the command text.
  • For the later steps that call ls and configure actions/upload-artifact, avoid using ${{ inputs.output_dir }} directly in shell commands as well: use an env mapping and shell variables for commands, while keeping ${{ ... }} only in YAML keys/values that are not executed as shell.

All of this can be done within .github/workflows/canton-reports.yaml without changing behavior: the Python script still gets the same arguments, and artifacts are uploaded from the same directory, but the shell never sees raw GitHub expression syntax that can expand to untrusted content.

Suggested changeset 1
.github/workflows/canton-reports.yaml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/canton-reports.yaml b/.github/workflows/canton-reports.yaml
--- a/.github/workflows/canton-reports.yaml
+++ b/.github/workflows/canton-reports.yaml
@@ -49,31 +49,39 @@
           python-version: '3.11'
           
       - name: Generate Canton wallet reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
+          USE_MOCK_DATA: ${{ inputs.use_mock_data }}
+          VALIDATOR_ONLY: ${{ inputs.validator_only }}
+          NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
+          DAYS: ${{ inputs.days }}
         run: |
-          mkdir -p ${{ inputs.output_dir }}
+          mkdir -p "$OUTPUT_DIR"
           
-          ARGS="--output-dir ${{ inputs.output_dir }}"
+          ARGS="--output-dir $OUTPUT_DIR"
           
-          if [ "${{ inputs.use_mock_data }}" == "true" ]; then
+          if [ "$USE_MOCK_DATA" = "true" ]; then
             ARGS="$ARGS --mock"
           fi
           
-          if [ "${{ inputs.validator_only }}" == "true" ]; then
+          if [ "$VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --validator-only"
           fi
           
-          if [ "${{ inputs.non_validator_only }}" == "true" ]; then
+          if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --non-validator-only"
           fi
           
-          ARGS="$ARGS --days ${{ inputs.days }}"
+          ARGS="$ARGS --days $DAYS"
           
           python3 scripts/generate_canton_reports.py $ARGS
           
       - name: List generated reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
         run: |
           echo "Generated reports:"
-          ls -lh ${{ inputs.output_dir }}
+          ls -lh "$OUTPUT_DIR"
           
       - name: Upload reports as artifacts
         uses: actions/upload-artifact@v4
EOF
@@ -49,31 +49,39 @@
python-version: '3.11'

- name: Generate Canton wallet reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
USE_MOCK_DATA: ${{ inputs.use_mock_data }}
VALIDATOR_ONLY: ${{ inputs.validator_only }}
NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
DAYS: ${{ inputs.days }}
run: |
mkdir -p ${{ inputs.output_dir }}
mkdir -p "$OUTPUT_DIR"

ARGS="--output-dir ${{ inputs.output_dir }}"
ARGS="--output-dir $OUTPUT_DIR"

if [ "${{ inputs.use_mock_data }}" == "true" ]; then
if [ "$USE_MOCK_DATA" = "true" ]; then
ARGS="$ARGS --mock"
fi

if [ "${{ inputs.validator_only }}" == "true" ]; then
if [ "$VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --validator-only"
fi

if [ "${{ inputs.non_validator_only }}" == "true" ]; then
if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --non-validator-only"
fi

ARGS="$ARGS --days ${{ inputs.days }}"
ARGS="$ARGS --days $DAYS"

python3 scripts/generate_canton_reports.py $ARGS

- name: List generated reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
run: |
echo "Generated reports:"
ls -lh ${{ inputs.output_dir }}
ls -lh "$OUTPUT_DIR"

- name: Upload reports as artifacts
uses: actions/upload-artifact@v4
Copilot is powered by AI and may make mistakes. Always verify output.

ARGS="--output-dir ${{ inputs.output_dir }}"

if [ "${{ inputs.use_mock_data }}" == "true" ]; then

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.use_mock_data }
, which may be controlled by an external user.

Copilot Autofix

AI 9 days ago

In general, to fix GitHub Actions code injection issues you should: (1) assign any untrusted or user-controlled ${{ inputs.* }} values to environment variables via the env: block of the step, and (2) only reference them inside the shell using native shell syntax ($VAR), never ${{ env.VAR }}. If you need boolean logic, do it at the shell level using the environment variables’ values.

For this workflow, the best fix without changing functionality is:

  • Add an env: section to the “Generate Canton wallet reports” step to capture all relevant inputs (OUTPUT_DIR, USE_MOCK_DATA, VALIDATOR_ONLY, NON_VALIDATOR_ONLY, DAYS) from their ${{ inputs.* }} values.
  • In the run: script:
    • Replace mkdir -p ${{ inputs.output_dir }} with mkdir -p "$OUTPUT_DIR".
    • Initialize ARGS using $OUTPUT_DIR instead of ${{ inputs.output_dir }}.
    • Replace if [ "${{ inputs.use_mock_data }}" == "true" ]; then with if [ "$USE_MOCK_DATA" = "true" ]; then (and similarly for the other two booleans).
    • Replace ARGS="$ARGS --days ${{ inputs.days }}" with ARGS="$ARGS --days $DAYS".
  • In the “List generated reports” and “Upload reports as artifacts” steps, move ${{ inputs.output_dir }} into an env var as well and use $OUTPUT_DIR in the shell commands and artifact path. This keeps behavior but removes expression expansion from within shell code and paths.

No new methods or external libraries are needed; we only adjust the YAML for the workflow and use standard shell variable expansion.

Suggested changeset 1
.github/workflows/canton-reports.yaml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/canton-reports.yaml b/.github/workflows/canton-reports.yaml
--- a/.github/workflows/canton-reports.yaml
+++ b/.github/workflows/canton-reports.yaml
@@ -49,31 +49,39 @@
           python-version: '3.11'
           
       - name: Generate Canton wallet reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
+          USE_MOCK_DATA: ${{ inputs.use_mock_data }}
+          VALIDATOR_ONLY: ${{ inputs.validator_only }}
+          NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
+          DAYS: ${{ inputs.days }}
         run: |
-          mkdir -p ${{ inputs.output_dir }}
+          mkdir -p "$OUTPUT_DIR"
           
-          ARGS="--output-dir ${{ inputs.output_dir }}"
+          ARGS="--output-dir $OUTPUT_DIR"
           
-          if [ "${{ inputs.use_mock_data }}" == "true" ]; then
+          if [ "$USE_MOCK_DATA" = "true" ]; then
             ARGS="$ARGS --mock"
           fi
           
-          if [ "${{ inputs.validator_only }}" == "true" ]; then
+          if [ "$VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --validator-only"
           fi
           
-          if [ "${{ inputs.non_validator_only }}" == "true" ]; then
+          if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --non-validator-only"
           fi
           
-          ARGS="$ARGS --days ${{ inputs.days }}"
+          ARGS="$ARGS --days $DAYS"
           
           python3 scripts/generate_canton_reports.py $ARGS
           
       - name: List generated reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
         run: |
           echo "Generated reports:"
-          ls -lh ${{ inputs.output_dir }}
+          ls -lh "$OUTPUT_DIR"
           
       - name: Upload reports as artifacts
         uses: actions/upload-artifact@v4
EOF
@@ -49,31 +49,39 @@
python-version: '3.11'

- name: Generate Canton wallet reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
USE_MOCK_DATA: ${{ inputs.use_mock_data }}
VALIDATOR_ONLY: ${{ inputs.validator_only }}
NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
DAYS: ${{ inputs.days }}
run: |
mkdir -p ${{ inputs.output_dir }}
mkdir -p "$OUTPUT_DIR"

ARGS="--output-dir ${{ inputs.output_dir }}"
ARGS="--output-dir $OUTPUT_DIR"

if [ "${{ inputs.use_mock_data }}" == "true" ]; then
if [ "$USE_MOCK_DATA" = "true" ]; then
ARGS="$ARGS --mock"
fi

if [ "${{ inputs.validator_only }}" == "true" ]; then
if [ "$VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --validator-only"
fi

if [ "${{ inputs.non_validator_only }}" == "true" ]; then
if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --non-validator-only"
fi

ARGS="$ARGS --days ${{ inputs.days }}"
ARGS="$ARGS --days $DAYS"

python3 scripts/generate_canton_reports.py $ARGS

- name: List generated reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
run: |
echo "Generated reports:"
ls -lh ${{ inputs.output_dir }}
ls -lh "$OUTPUT_DIR"

- name: Upload reports as artifacts
uses: actions/upload-artifact@v4
Copilot is powered by AI and may make mistakes. Always verify output.
ARGS="$ARGS --mock"
fi

if [ "${{ inputs.validator_only }}" == "true" ]; then

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.validator_only }
, which may be controlled by an external user.

Copilot Autofix

AI 9 days ago

To fix the problem, we should stop using ${{ inputs.* }} directly inside the shell script body. Instead, we will map all workflow inputs to environment variables via the env: section of the step and then use standard shell variable expansion like $VALIDATOR_ONLY etc. This aligns with GitHub’s recommended pattern and prevents expression-based code injection.

Concretely, in the “Generate Canton wallet reports” step:

  • Add an env: block that assigns each input to an environment variable, e.g. VALIDATOR_ONLY: ${{ inputs.validator_only }}, OUTPUT_DIR: ${{ inputs.output_dir }}, USE_MOCK_DATA: ${{ inputs.use_mock_data }}, NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}, DAYS: ${{ inputs.days }}.
  • In the run: script:
    • Replace mkdir -p ${{ inputs.output_dir }} with mkdir -p "$OUTPUT_DIR".
    • Initialize ARGS="--output-dir \"$OUTPUT_DIR\"" instead of using ${{ inputs.output_dir }} directly.
    • Change the if checks from if [ "${{ inputs.use_mock_data }}" == "true" ]; then etc. to if [ "$USE_MOCK_DATA" = "true" ]; then, similarly for VALIDATOR_ONLY and NON_VALIDATOR_ONLY.
    • Replace ARGS="$ARGS --days ${{ inputs.days }}" with ARGS="$ARGS --days $DAYS".
  • Quote variables properly to avoid word splitting and preserve paths with spaces.

Other steps (List generated reports, Upload reports as artifacts) still use ${{ inputs.output_dir }} in non-shell contexts or in simple path usage. These are not subject to the same injection pattern because they are not being parsed by a shell via run:, so we can leave them unchanged.

All changes occur within .github/workflows/canton-reports.yaml in the shown step, and no new imports or external libraries are needed.

Suggested changeset 1
.github/workflows/canton-reports.yaml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/canton-reports.yaml b/.github/workflows/canton-reports.yaml
--- a/.github/workflows/canton-reports.yaml
+++ b/.github/workflows/canton-reports.yaml
@@ -49,24 +49,30 @@
           python-version: '3.11'
           
       - name: Generate Canton wallet reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
+          USE_MOCK_DATA: ${{ inputs.use_mock_data }}
+          VALIDATOR_ONLY: ${{ inputs.validator_only }}
+          NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
+          DAYS: ${{ inputs.days }}
         run: |
-          mkdir -p ${{ inputs.output_dir }}
+          mkdir -p "$OUTPUT_DIR"
           
-          ARGS="--output-dir ${{ inputs.output_dir }}"
+          ARGS="--output-dir \"$OUTPUT_DIR\""
           
-          if [ "${{ inputs.use_mock_data }}" == "true" ]; then
+          if [ "$USE_MOCK_DATA" = "true" ]; then
             ARGS="$ARGS --mock"
           fi
           
-          if [ "${{ inputs.validator_only }}" == "true" ]; then
+          if [ "$VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --validator-only"
           fi
           
-          if [ "${{ inputs.non_validator_only }}" == "true" ]; then
+          if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --non-validator-only"
           fi
           
-          ARGS="$ARGS --days ${{ inputs.days }}"
+          ARGS="$ARGS --days $DAYS"
           
           python3 scripts/generate_canton_reports.py $ARGS
           
EOF
@@ -49,24 +49,30 @@
python-version: '3.11'

- name: Generate Canton wallet reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
USE_MOCK_DATA: ${{ inputs.use_mock_data }}
VALIDATOR_ONLY: ${{ inputs.validator_only }}
NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
DAYS: ${{ inputs.days }}
run: |
mkdir -p ${{ inputs.output_dir }}
mkdir -p "$OUTPUT_DIR"

ARGS="--output-dir ${{ inputs.output_dir }}"
ARGS="--output-dir \"$OUTPUT_DIR\""

if [ "${{ inputs.use_mock_data }}" == "true" ]; then
if [ "$USE_MOCK_DATA" = "true" ]; then
ARGS="$ARGS --mock"
fi

if [ "${{ inputs.validator_only }}" == "true" ]; then
if [ "$VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --validator-only"
fi

if [ "${{ inputs.non_validator_only }}" == "true" ]; then
if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --non-validator-only"
fi

ARGS="$ARGS --days ${{ inputs.days }}"
ARGS="$ARGS --days $DAYS"

python3 scripts/generate_canton_reports.py $ARGS

Copilot is powered by AI and may make mistakes. Always verify output.
ARGS="$ARGS --validator-only"
fi

if [ "${{ inputs.non_validator_only }}" == "true" ]; then

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.non_validator_only }
, which may be controlled by an external user.

Copilot Autofix

AI 9 days ago

In general, to prevent code injection in GitHub Actions shell steps, interpolate untrusted inputs into environment variables at the workflow level, then reference them using the shell’s native variable syntax ($VAR, "${VAR}") inside run:. Avoid ${{ ... }} within the script body. This prevents user-controlled content from being interpreted by the GitHub expression engine and injected into the shell.

For this workflow, the safest fix is to:

  1. Add an env: block on the Generate Canton wallet reports step that maps each used input (output_dir, use_mock_data, validator_only, non_validator_only, days) into an environment variable, e.g. OUTPUT_DIR: ${{ inputs.output_dir }}.
  2. Rewrite the shell script to use those environment variables via shell syntax only, e.g. mkdir -p "$OUTPUT_DIR", if [ "$USE_MOCK_DATA" = "true" ]; then ..., ARGS="$ARGS --days $DAYS", and python3 scripts/generate_canton_reports.py $ARGS.
  3. Apply the same pattern to the List generated reports step and the upload-artifact path, by defining OUTPUT_DIR in env: and using $OUTPUT_DIR in run: and with: where appropriate (for with: we still must use ${{ env.OUTPUT_DIR }}, but that’s not a shell context).

All edits are confined to .github/workflows/canton-reports.yaml within the provided regions: add env: blocks to the two shell steps and the upload step, and replace usages of ${{ inputs.* }} inside run: with the corresponding shell variables. No new methods or external libraries are needed.

Suggested changeset 1
.github/workflows/canton-reports.yaml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/canton-reports.yaml b/.github/workflows/canton-reports.yaml
--- a/.github/workflows/canton-reports.yaml
+++ b/.github/workflows/canton-reports.yaml
@@ -49,36 +49,46 @@
           python-version: '3.11'
           
       - name: Generate Canton wallet reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
+          USE_MOCK_DATA: ${{ inputs.use_mock_data }}
+          VALIDATOR_ONLY: ${{ inputs.validator_only }}
+          NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
+          DAYS: ${{ inputs.days }}
         run: |
-          mkdir -p ${{ inputs.output_dir }}
+          mkdir -p "$OUTPUT_DIR"
           
-          ARGS="--output-dir ${{ inputs.output_dir }}"
+          ARGS="--output-dir $OUTPUT_DIR"
           
-          if [ "${{ inputs.use_mock_data }}" == "true" ]; then
+          if [ "$USE_MOCK_DATA" = "true" ]; then
             ARGS="$ARGS --mock"
           fi
           
-          if [ "${{ inputs.validator_only }}" == "true" ]; then
+          if [ "$VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --validator-only"
           fi
           
-          if [ "${{ inputs.non_validator_only }}" == "true" ]; then
+          if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --non-validator-only"
           fi
           
-          ARGS="$ARGS --days ${{ inputs.days }}"
+          ARGS="$ARGS --days $DAYS"
           
           python3 scripts/generate_canton_reports.py $ARGS
           
       - name: List generated reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
         run: |
           echo "Generated reports:"
-          ls -lh ${{ inputs.output_dir }}
+          ls -lh "$OUTPUT_DIR"
           
       - name: Upload reports as artifacts
         uses: actions/upload-artifact@v4
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
         with:
           name: canton-wallet-reports-${{ github.run_id }}
-          path: ${{ inputs.output_dir }}/*.csv
+          path: ${{ env.OUTPUT_DIR }}/*.csv
           retention-days: 90
           if-no-files-found: error
EOF
@@ -49,36 +49,46 @@
python-version: '3.11'

- name: Generate Canton wallet reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
USE_MOCK_DATA: ${{ inputs.use_mock_data }}
VALIDATOR_ONLY: ${{ inputs.validator_only }}
NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
DAYS: ${{ inputs.days }}
run: |
mkdir -p ${{ inputs.output_dir }}
mkdir -p "$OUTPUT_DIR"

ARGS="--output-dir ${{ inputs.output_dir }}"
ARGS="--output-dir $OUTPUT_DIR"

if [ "${{ inputs.use_mock_data }}" == "true" ]; then
if [ "$USE_MOCK_DATA" = "true" ]; then
ARGS="$ARGS --mock"
fi

if [ "${{ inputs.validator_only }}" == "true" ]; then
if [ "$VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --validator-only"
fi

if [ "${{ inputs.non_validator_only }}" == "true" ]; then
if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --non-validator-only"
fi

ARGS="$ARGS --days ${{ inputs.days }}"
ARGS="$ARGS --days $DAYS"

python3 scripts/generate_canton_reports.py $ARGS

- name: List generated reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
run: |
echo "Generated reports:"
ls -lh ${{ inputs.output_dir }}
ls -lh "$OUTPUT_DIR"

- name: Upload reports as artifacts
uses: actions/upload-artifact@v4
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
with:
name: canton-wallet-reports-${{ github.run_id }}
path: ${{ inputs.output_dir }}/*.csv
path: ${{ env.OUTPUT_DIR }}/*.csv
retention-days: 90
if-no-files-found: error
Copilot is powered by AI and may make mistakes. Always verify output.
ARGS="$ARGS --non-validator-only"
fi

ARGS="$ARGS --days ${{ inputs.days }}"

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.days }
, which may be controlled by an external user.

Copilot Autofix

AI 9 days ago

In general, to fix this pattern in GitHub Actions, any untrusted input should first be assigned to an environment variable via ${{ }} in the YAML, and then referenced using the shell’s native variable expansion ($VAR) inside the run: script. This avoids injecting GitHub expressions directly into the command string and lets the shell treat the value as plain data.

For this specific workflow, we should:

  • Move all ${{ inputs.* }} usages within run: blocks into env: declarations for the step.
  • In the shell script, read those environment variables using $OUTPUT_DIR, $USE_MOCK_DATA, $VALIDATOR_ONLY, $NON_VALIDATOR_ONLY, and $DAYS.
  • Also update the later List generated reports step to use $OUTPUT_DIR rather than ${{ inputs.output_dir }} for consistency and safety.

Concretely, in .github/workflows/canton-reports.yaml:

  • In the “Generate Canton wallet reports” step, add an env: section mapping each input to a corresponding env var, and rewrite the script to use those env vars instead of ${{ inputs.* }}.
  • In the “List generated reports” step, add an env: section for OUTPUT_DIR and change ls -lh ${{ inputs.output_dir }} to ls -lh "$OUTPUT_DIR".
    No additional methods or external libraries are needed; this is purely a YAML and shell change.
Suggested changeset 1
.github/workflows/canton-reports.yaml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/canton-reports.yaml b/.github/workflows/canton-reports.yaml
--- a/.github/workflows/canton-reports.yaml
+++ b/.github/workflows/canton-reports.yaml
@@ -49,31 +49,41 @@
           python-version: '3.11'
           
       - name: Generate Canton wallet reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
+          USE_MOCK_DATA: ${{ inputs.use_mock_data }}
+          VALIDATOR_ONLY: ${{ inputs.validator_only }}
+          NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
+          DAYS: ${{ inputs.days }}
         run: |
-          mkdir -p ${{ inputs.output_dir }}
+          mkdir -p "$OUTPUT_DIR"
           
-          ARGS="--output-dir ${{ inputs.output_dir }}"
+          ARGS="--output-dir \"$OUTPUT_DIR\""
           
-          if [ "${{ inputs.use_mock_data }}" == "true" ]; then
+          if [ "$USE_MOCK_DATA" = "true" ]; then
             ARGS="$ARGS --mock"
           fi
           
-          if [ "${{ inputs.validator_only }}" == "true" ]; then
+          if [ "$VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --validator-only"
           fi
           
-          if [ "${{ inputs.non_validator_only }}" == "true" ]; then
+          if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --non-validator-only"
           fi
           
-          ARGS="$ARGS --days ${{ inputs.days }}"
+          ARGS="$ARGS --days \"$DAYS\""
           
-          python3 scripts/generate_canton_reports.py $ARGS
+          # shellcheck disable=SC2086
+          eval set -- $ARGS
+          python3 scripts/generate_canton_reports.py "$@"
           
       - name: List generated reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
         run: |
           echo "Generated reports:"
-          ls -lh ${{ inputs.output_dir }}
+          ls -lh "$OUTPUT_DIR"
           
       - name: Upload reports as artifacts
         uses: actions/upload-artifact@v4
EOF
@@ -49,31 +49,41 @@
python-version: '3.11'

- name: Generate Canton wallet reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
USE_MOCK_DATA: ${{ inputs.use_mock_data }}
VALIDATOR_ONLY: ${{ inputs.validator_only }}
NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
DAYS: ${{ inputs.days }}
run: |
mkdir -p ${{ inputs.output_dir }}
mkdir -p "$OUTPUT_DIR"

ARGS="--output-dir ${{ inputs.output_dir }}"
ARGS="--output-dir \"$OUTPUT_DIR\""

if [ "${{ inputs.use_mock_data }}" == "true" ]; then
if [ "$USE_MOCK_DATA" = "true" ]; then
ARGS="$ARGS --mock"
fi

if [ "${{ inputs.validator_only }}" == "true" ]; then
if [ "$VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --validator-only"
fi

if [ "${{ inputs.non_validator_only }}" == "true" ]; then
if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --non-validator-only"
fi

ARGS="$ARGS --days ${{ inputs.days }}"
ARGS="$ARGS --days \"$DAYS\""

python3 scripts/generate_canton_reports.py $ARGS
# shellcheck disable=SC2086
eval set -- $ARGS
python3 scripts/generate_canton_reports.py "$@"

- name: List generated reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
run: |
echo "Generated reports:"
ls -lh ${{ inputs.output_dir }}
ls -lh "$OUTPUT_DIR"

- name: Upload reports as artifacts
uses: actions/upload-artifact@v4
Copilot is powered by AI and may make mistakes. Always verify output.
- name: List generated reports
run: |
echo "Generated reports:"
ls -lh ${{ inputs.output_dir }}

Check warning

Code scanning / CodeQL

Code injection Medium

Potential code injection in
${ inputs.output_dir }
, which may be controlled by an external user.

Copilot Autofix

AI 9 days ago

To fix this, we should stop interpolating inputs.output_dir (and the other user-controllable inputs) directly into the shell commands with ${{ ... }} and instead assign them to environment variables via env: and reference them using native shell syntax ($OUTPUT_DIR, $USE_MOCK_DATA, etc.). This follows GitHub’s recommended mitigation pattern and prevents shell from interpreting injected characters as code.

Concretely, in .github/workflows/canton-reports.yaml:

  • For the “Generate Canton wallet reports” step:
    • Add an env: block that maps all workflow inputs used in the script (output_dir, use_mock_data, validator_only, non_validator_only, days) to environment variables (e.g., OUTPUT_DIR: ${{ inputs.output_dir }}, etc.).
    • In the run: script:
      • Replace mkdir -p ${{ inputs.output_dir }} with mkdir -p "$OUTPUT_DIR".
      • Initialize ARGS with --output-dir "$OUTPUT_DIR" instead of referencing the expression directly.
      • Replace all if [ "${{ inputs.X }}" == "true" ]; then branches to check the corresponding env var: if [ "$USE_MOCK_DATA" = "true" ]; then etc.
      • Replace ARGS="$ARGS --days ${{ inputs.days }}" with ARGS="$ARGS --days $DAYS".
  • For the “List generated reports” step:
    • Add an env: block with OUTPUT_DIR: ${{ inputs.output_dir }}.
    • Replace ls -lh ${{ inputs.output_dir }} with ls -lh "$OUTPUT_DIR".

We leave non-shell contexts (like artifact path:) unchanged, since they are not interpreted as shell commands. This preserves existing functionality while eliminating direct interpolation of untrusted values into the shell.

Suggested changeset 1
.github/workflows/canton-reports.yaml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/canton-reports.yaml b/.github/workflows/canton-reports.yaml
--- a/.github/workflows/canton-reports.yaml
+++ b/.github/workflows/canton-reports.yaml
@@ -49,31 +49,39 @@
           python-version: '3.11'
           
       - name: Generate Canton wallet reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
+          USE_MOCK_DATA: ${{ inputs.use_mock_data }}
+          VALIDATOR_ONLY: ${{ inputs.validator_only }}
+          NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
+          DAYS: ${{ inputs.days }}
         run: |
-          mkdir -p ${{ inputs.output_dir }}
+          mkdir -p "$OUTPUT_DIR"
           
-          ARGS="--output-dir ${{ inputs.output_dir }}"
+          ARGS="--output-dir \"$OUTPUT_DIR\""
           
-          if [ "${{ inputs.use_mock_data }}" == "true" ]; then
+          if [ "$USE_MOCK_DATA" = "true" ]; then
             ARGS="$ARGS --mock"
           fi
           
-          if [ "${{ inputs.validator_only }}" == "true" ]; then
+          if [ "$VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --validator-only"
           fi
           
-          if [ "${{ inputs.non_validator_only }}" == "true" ]; then
+          if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
             ARGS="$ARGS --non-validator-only"
           fi
           
-          ARGS="$ARGS --days ${{ inputs.days }}"
+          ARGS="$ARGS --days $DAYS"
           
           python3 scripts/generate_canton_reports.py $ARGS
           
       - name: List generated reports
+        env:
+          OUTPUT_DIR: ${{ inputs.output_dir }}
         run: |
           echo "Generated reports:"
-          ls -lh ${{ inputs.output_dir }}
+          ls -lh "$OUTPUT_DIR"
           
       - name: Upload reports as artifacts
         uses: actions/upload-artifact@v4
EOF
@@ -49,31 +49,39 @@
python-version: '3.11'

- name: Generate Canton wallet reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
USE_MOCK_DATA: ${{ inputs.use_mock_data }}
VALIDATOR_ONLY: ${{ inputs.validator_only }}
NON_VALIDATOR_ONLY: ${{ inputs.non_validator_only }}
DAYS: ${{ inputs.days }}
run: |
mkdir -p ${{ inputs.output_dir }}
mkdir -p "$OUTPUT_DIR"

ARGS="--output-dir ${{ inputs.output_dir }}"
ARGS="--output-dir \"$OUTPUT_DIR\""

if [ "${{ inputs.use_mock_data }}" == "true" ]; then
if [ "$USE_MOCK_DATA" = "true" ]; then
ARGS="$ARGS --mock"
fi

if [ "${{ inputs.validator_only }}" == "true" ]; then
if [ "$VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --validator-only"
fi

if [ "${{ inputs.non_validator_only }}" == "true" ]; then
if [ "$NON_VALIDATOR_ONLY" = "true" ]; then
ARGS="$ARGS --non-validator-only"
fi

ARGS="$ARGS --days ${{ inputs.days }}"
ARGS="$ARGS --days $DAYS"

python3 scripts/generate_canton_reports.py $ARGS

- name: List generated reports
env:
OUTPUT_DIR: ${{ inputs.output_dir }}
run: |
echo "Generated reports:"
ls -lh ${{ inputs.output_dir }}
ls -lh "$OUTPUT_DIR"

- name: Upload reports as artifacts
uses: actions/upload-artifact@v4
Copilot is powered by AI and may make mistakes. Always verify output.
@derrix060 derrix060 closed this Feb 2, 2026
@derrix060 derrix060 deleted the copilot/automate-weekly-csv-reports-ang-812 branch February 2, 2026 17:20
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.

2 participants