Skip to content

fix: Argo workflows parameters as env variables#2756

Merged
saikonen merged 9 commits into
masterfrom
fix/argo-workflows-parameters-as-env
Jun 9, 2026
Merged

fix: Argo workflows parameters as env variables#2756
saikonen merged 9 commits into
masterfrom
fix/argo-workflows-parameters-as-env

Conversation

@saikonen

Copy link
Copy Markdown
Collaborator

Rework argo params handling to pass values as environment variables instead of part of the CLI. Allows overriding the param values via environment if necessary.

@saikonen

Copy link
Copy Markdown
Collaborator Author

kubernetes / argo init uses METAFLOW_INIT_SCRIPT which would have a collision with this implementation if anyone has a --script parameter in their flow. This would possibly necessitate adding script to the list of reserved params, or raising an exception in the argo / kubernetes case if there is a collision.

@saikonen
saikonen marked this pull request as ready for review January 27, 2026 14:29
@saikonen

Copy link
Copy Markdown
Collaborator Author

@greptile

@greptile-apps

greptile-apps Bot commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR reworks Argo Workflows parameter passing from inline CLI arguments to environment variables (METAFLOW_INIT_*) set via a generated shell script. This reduces command-line length and enables parameter value overriding through the environment.

  • New set_parameters.py: Replaces param_val.py. Accepts base64-encoded parameter values as CSV arguments, decodes them, and writes export statements to a temporary shell script that is sourced before step execution.
  • Null-default handling: Parameters with None defaults are flagged with a "t"/"f" marker in the CSV format. When the runtime value is JSON null and the default was None, the parameter is skipped (not exported), making optional parameters work correctly.
  • Reserved parameter names: "script" is now a reserved name for Argo Workflows to avoid conflicts with Argo internals.
  • Approach mirrors Airflow: The env-var-based approach is consistent with how the Airflow plugin (airflow/plumbing/set_parameters.py) already handles parameters.

Confidence Score: 3/5

  • The core logic is sound, but the unquoted shell export values (flagged in a previous thread) represent a real security concern that should be addressed before merging.
  • The parameter CSV format is safe (base64 doesn't contain commas or spaces), null-default handling is correct, and the reserved-name check is properly placed. However, the shell export values are written without quoting, which allows command substitution when the script is sourced — a security concern previously flagged. The decimal chmod literal is a minor readability issue. No tests are included for the new module.
  • metaflow/plugins/argo/set_parameters.py needs attention for the unquoted shell export values (security) and should have unit test coverage added.

Important Files Changed

Filename Overview
metaflow/plugins/argo/argo_workflows.py Reworks parameter passing from CLI arguments to environment variables via a generated shell script. Adds reserved parameter name check ("script") and random temp filename generation. Logic is sound; the Argo template expression and base64 encoding are safe for the CSV format used.
metaflow/plugins/argo/param_val.py Deleted in favor of the new set_parameters.py module which subsumes its functionality (parse_parameter_value is preserved and extended).
metaflow/plugins/argo/set_parameters.py New module that parses base64-encoded parameter values and writes shell export statements to a file. Contains a shell injection concern where parameter values are written unquoted into export statements, and the none_default/null-skipping logic for optional parameters is correct but relies on string comparison of JSON-serialized null.

Sequence Diagram

sequenceDiagram
    participant Argo as Argo Workflow Engine
    participant Shell as Bash Shell (Container)
    participant SetParams as set_parameters.py
    participant File as Temp Export File
    participant MF as Metaflow CLI (step)

    Argo->>Shell: Inject workflow.parameters (base64-encoded)
    Shell->>SetParams: python -m set_parameters <file> name,flag,b64val ...
    SetParams->>SetParams: base64 decode + JSON parse each param
    SetParams->>SetParams: Skip params where none_default=True and value="null"
    SetParams->>File: Write export METAFLOW_INIT_<NAME>=<json_value>
    Shell->>Shell: source temp file (. `pwd`/<file>)
    Note over Shell: METAFLOW_INIT_* env vars now set
    Shell->>MF: Execute bootstrap + metaflow step command
    MF->>MF: Click reads METAFLOW_INIT_* for parameter values
Loading

Last reviewed commit: 4db34ef

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

3 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

Comment thread metaflow/plugins/argo/argo_workflows.py
Comment on lines +31 to +37
f.write(
"export METAFLOW_INIT_%s=%s\n"
% (
k.upper().replace("-", "_"),
parsed_value,
)
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unquoted shell export values risk expansion

The export statement writes parsed_value (a JSON-serialized string) without shell quoting. For string parameters, json.dumps wraps the value in double quotes (e.g., "hello world" becomes "hello world"), which provides some shell protection. However, shell metacharacters like $, backticks, and $(...) inside double quotes are still subject to variable expansion and command substitution when the file is sourced.

For example, a parameter value of $(whoami) would produce:

export METAFLOW_INIT_FOO="$(whoami)"

which executes the command substitution when sourced.

Consider using shlex.quote() to wrap the value in single quotes:

import shlex
f.write(
    "export METAFLOW_INIT_%s=%s\n"
    % (
        k.upper().replace("-", "_"),
        shlex.quote(parsed_value),
    )
)

Note: the existing Airflow set_parameters.py has the same pattern, but since this is a new file, it's worth fixing here.

@saikonen saikonen Jun 9, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Same pattern is used in step-functions and airflow implementations so if there is an actual issue here, it needs to be fixed in all three.

Opting to go with the current implementation, as shlex.quote forces outer quotes to the value which completely breaks expectations.

Comment thread metaflow/plugins/argo/set_parameters.py Outdated
parsed_value,
)
)
os.chmod(output_file, 509)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Decimal literal obscures file permissions

Using 509 (decimal) makes it hard to understand the intended file permissions at a glance. This is 0o775 (rwxrwxr-x) in octal. Using the octal literal makes the intent immediately clear and is the standard convention for chmod calls.

Suggested change
os.chmod(output_file, 509)
os.chmod(output_file, 0o775)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@saikonen
saikonen merged commit d74583a into master Jun 9, 2026
34 checks passed
@saikonen
saikonen deleted the fix/argo-workflows-parameters-as-env branch June 9, 2026 19:21
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.

1 participant