Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/api/openapi/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,11 @@
"environment": {
"$ref": "#/components/schemas/Environment"
},
"inputs": {
"additionalProperties": true,
"description": "Resolved input values for a workflow run.",
"type": "object"
},
"jobAgent": {
"$ref": "#/components/schemas/JobAgent"
},
Expand Down
5 changes: 5 additions & 0 deletions apps/api/openapi/schemas/jobs.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ local JobPropertyKeys = std.objectFields(Job.properties);
workflowJob: openapi.schemaRef('WorkflowJob'),
workflowRun: openapi.schemaRef('WorkflowRun'),
version: openapi.schemaRef('DeploymentVersion'),
inputs: {
type: 'object',
additionalProperties: true,
description: 'Resolved input values for a workflow run.',
},
variables: {
type: 'object',
additionalProperties: openapi.schemaRef('LiteralValue'),
Expand Down
4 changes: 4 additions & 0 deletions apps/api/src/types/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,10 @@ export interface components {
DispatchContext: {
deployment?: components["schemas"]["Deployment"];
environment?: components["schemas"]["Environment"];
/** @description Resolved input values for a workflow run. */
inputs?: {
[key: string]: unknown;
};
jobAgent: components["schemas"]["JobAgent"];
jobAgentConfig: components["schemas"]["JobAgentConfig"];
release?: components["schemas"]["Release"];
Expand Down
1 change: 1 addition & 0 deletions github/get-job-inputs/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions integrations/github-get-job-inputs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ async function run() {
workspace: { id: job.workspaceId },
environment: dispatchContext?.environment,
deployment: dispatchContext?.deployment,
input: dispatchContext?.inputs,

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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check the DispatchContext schema to understand if inputs can contain sensitive data

# Look for the DispatchContext type definition and inputs field
ast-grep --pattern $'interface DispatchContext {
  $$$
  inputs$_
  $$$
}'

# Also search for any documentation or comments about inputs
rg -nP -C5 'inputs.*:.*\{' --type=ts --glob '**/schemas/**' --glob '**/types/**'

# Check if there are any sanitization or filtering patterns for inputs
rg -nP '(secret|password|token|key|credential)' --type=ts --iglob '*dispatch*' --iglob '*input*' -C3

Repository: ctrlplanedev/ctrlplane

Length of output: 22669


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and print the relevant section of the action entrypoint
echo "### integrations/github-get-job-inputs/src/index.ts (around line 60-120)"
nl -ba integrations/github-get-job-inputs/src/index.ts | sed -n '60,130p'

# Find where setOutputsRecursively is defined/used
echo "### Search for setOutputsRecursively definition"
rg -n "setOutputsRecursively" integrations/github-get-job-inputs/src -S

# Print the file(s) containing setOutputsRecursively
echo "### Print setOutputsRecursively implementation (if in-repo)"
FILES=$(rg -l "setOutputsRecursively" integrations/github-get-job-inputs/src -S || true)
if [ -n "${FILES:-}" ]; then
  for f in $FILES; do
    echo "---- $f ----"
    nl -ba "$f" | sed -n '1,220p'
  done
fi

# Determine where dispatchContext comes from and its type import/definition
echo "### Search for dispatchContext usage and its type/source"
rg -n "dispatchContext" integrations/github-get-job-inputs/src -S

# Also locate the typed DispatchContext import (if any) and show its type shape
echo "### Search for DispatchContext type references in this integration"
rg -n "DispatchContext" integrations/github-get-job-inputs/src -S

Repository: ctrlplanedev/ctrlplane

Length of output: 200


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "### integrations/github-get-job-inputs/src/index.ts (around line 60-130)"
sed -n '60,130p' integrations/github-get-job-inputs/src/index.ts | cat -n

echo "### Search for setOutputsRecursively definition/usage"
rg -n "setOutputsRecursively" integrations/github-get-job-inputs/src -S || true

echo "### Print candidate files that define setOutputsRecursively (if in-repo)"
FILES=$(rg -l "setOutputsRecursively" integrations/github-get-job-inputs/src -S || true)
if [ -n "${FILES:-}" ]; then
  for f in $FILES; do
    echo "---- $f ----"
    # show enough lines around the definition
    sed -n '1,220p' "$f" | cat -n
  done
fi

echo "### Search for dispatchContext usage"
rg -n "dispatchContext" integrations/github-get-job-inputs/src -S || true

echo "### Search for DispatchContext type references"
rg -n "DispatchContext" integrations/github-get-job-inputs/src -S || true

Repository: ctrlplanedev/ctrlplane

Length of output: 6394


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "### Search for sanitization/redaction in the integration"
rg -n "(sanitize|redact|mask|secret|token|password|key|credential)" integrations/github-get-job-inputs/src -S || true

echo "### Inspect OpenAPI DispatchContext type shape around inputs"
# show the exact lines from openapi generated types
sed -n '1560,1620p' apps/api/src/types/openapi.ts | cat -n

echo "### Search for setOutputAndLog usage / any overrides"
rg -n "setOutputAndLog|core\.info\(" integrations/github-get-job-inputs/src -S

Repository: ctrlplanedev/ctrlplane

Length of output: 4906


Prevent potential secret leakage by not recursively logging/setting outputs from dispatchContext?.inputs

  • integrations/github-get-job-inputs/src/index.ts sets input: dispatchContext?.inputs and passes it to setOutputsRecursively, which flattens every nested leaf and writes it to both core.setOutput(...) and core.info(...).
  • DispatchContext.inputs is typed as { [key: string]: unknown }, and there’s no value redaction/sanitization (only key name normalization), so any workflow input that contains a token/password/API key would be exposed in action logs and as outputs.
  • Minor: input (singular) is populated from inputs (plural); check if the naming is intentional for workflow compatibility.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integrations/github-get-job-inputs/src/index.ts` at line 86,
dispatchContext?.inputs is being passed directly into setOutputsRecursively (via
the property input) which flattens and writes every nested value to
core.setOutput/core.info and can leak secrets; change the code so that index.ts
does not pass raw dispatchContext?.inputs into setOutputsRecursively—either (a)
only pass a vetted whitelist of allowed keys, (b) redact sensitive-looking
values (e.g., keys containing "token"/"password"/"secret"/"key") before passing,
or (c) avoid recursive output logging entirely and instead expose only specific
safe fields; also confirm whether the singular property name input is
intentional and, if kept, ensure its contents are sanitized before any calls to
setOutputsRecursively or core.info to prevent secret exposure.

};

setOutputsRecursively(null, ghActionsJobObject);
Expand Down
Loading