-
Notifications
You must be signed in to change notification settings - Fork 807
Dummy gated release #935
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dummy gated release #935
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| name: "Artifactory OIDC Auth" | ||
| description: "Exchange GitHub OIDC token for Artifactory access and configure pip indexes" | ||
|
|
||
| inputs: | ||
| artifactory-url: | ||
| description: "Base Artifactory platform URL. Falls back to ARTIFACTORY_URL env var if not provided." | ||
| required: false | ||
| default: "" | ||
| oidc-provider-name: | ||
| description: "OIDC provider name configured in Artifactory" | ||
| required: false | ||
| default: "github-actions" | ||
| pypi-repo: | ||
| description: "Artifactory virtual PyPI repository name" | ||
| required: false | ||
| default: "virtual-pypi-thirdparty" | ||
|
|
||
| runs: | ||
| using: "composite" | ||
| steps: | ||
| - name: Exchange GitHub OIDC token for Artifactory token | ||
| shell: bash | ||
| env: | ||
| INPUT_ARTIFACTORY_URL: ${{ inputs.artifactory-url }} | ||
| OIDC_PROVIDER_NAME: ${{ inputs.oidc-provider-name }} | ||
| PYPI_REPO: ${{ inputs.pypi-repo }} | ||
| run: | | ||
| set -euo pipefail | ||
| ARTIFACTORY_URL="${INPUT_ARTIFACTORY_URL:-${ARTIFACTORY_URL:-}}" | ||
| if [ -z "${ARTIFACTORY_URL}" ]; then | ||
| echo "::error::ARTIFACTORY_URL is not set (pass as input or set as env var)"; exit 1 | ||
| fi | ||
|
|
||
| OIDC_JWT=$(curl -sS \ | ||
| "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${ARTIFACTORY_URL}" \ | ||
| -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" | jq -r '.value') | ||
|
|
||
| if [ -z "$OIDC_JWT" ] || [ "$OIDC_JWT" = "null" ]; then | ||
| echo "::error::Failed to obtain GitHub OIDC token"; exit 1 | ||
| fi | ||
|
|
||
| decode_seg() { local s="${1}"; local m=$(( ${#s} % 4 )); [ $m -ne 0 ] && s="${s}$(printf '=%.0s' $(seq 1 $((4-m))))"; echo "$s" | tr '_-' '/+' | base64 -d 2>/dev/null; } | ||
| PAYLOAD=$(decode_seg "$(echo "$OIDC_JWT" | cut -d. -f2)") | ||
| echo "OIDC token claims:" | ||
| echo " sub = $(echo "$PAYLOAD" | jq -r '.sub')" | ||
| echo " aud = $(echo "$PAYLOAD" | jq -r '.aud')" | ||
| echo " iss = $(echo "$PAYLOAD" | jq -r '.iss')" | ||
|
|
||
| RESP=$(curl -sS "${ARTIFACTORY_URL}/access/api/v1/oidc/token" \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d "{\"grant_type\":\"urn:ietf:params:oauth:grant-type:token-exchange\", | ||
| \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", | ||
| \"subject_token\":\"${OIDC_JWT}\", | ||
| \"provider_name\":\"${OIDC_PROVIDER_NAME}\"}") | ||
|
|
||
| ART_TOKEN=$(echo "$RESP" | jq -r '.access_token // empty') | ||
|
|
||
| if [ -z "$ART_TOKEN" ]; then | ||
| echo "::error::OIDC token exchange failed. Raw response (token field redacted):" | ||
| echo "$RESP" | jq 'if .access_token then .access_token="<redacted>" else . end' 2>/dev/null || echo "$RESP" | ||
| exit 1 | ||
| fi | ||
| echo "::add-mask::$ART_TOKEN" | ||
|
|
||
| HOST=$(echo "${ARTIFACTORY_URL}" | sed -E 's#^https?://##') | ||
| INDEX_URL="https://:${ART_TOKEN}@${HOST}/artifactory/api/pypi/${PYPI_REPO}/simple/" | ||
|
|
||
| echo "::add-mask::${INDEX_URL}" | ||
| echo "PIP_INDEX_URL=${INDEX_URL}" >> "$GITHUB_ENV" | ||
| echo "PIP_TRUSTED_HOST=${HOST}" >> "$GITHUB_ENV" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| name: Test and Deploy to PyPI | ||
|
|
||
| on: | ||
| release: | ||
| types: [published] | ||
| workflow_dispatch: | ||
|
|
||
| env: | ||
| ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }} | ||
|
|
||
| jobs: | ||
| test: | ||
| name: Test - Python ${{ matrix.python-version }} | ||
| runs-on: ${{ github.repository_owner == 'twilio-internal' && 'ubuntu-x64' || 'ubuntu-latest' }} | ||
| timeout-minutes: 20 | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Authenticate with Artifactory | ||
| uses: ./.github/actions/artifactory-oidc | ||
|
|
||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: ${{ matrix.python-version }} | ||
|
|
||
| - name: Install dependencies | ||
| run: | | ||
| pip install virtualenv --upgrade | ||
| make install test-install | ||
|
|
||
| - name: Run tests | ||
| run: make test-with-coverage | ||
|
|
||
| deploy: | ||
| name: Publish to PyPI | ||
| needs: [test] | ||
| runs-on: ${{ github.repository_owner == 'twilio-internal' && 'ubuntu-x64' || 'ubuntu-latest' }} | ||
| environment: pypi | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| attestations: write | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Authenticate with Artifactory | ||
| uses: ./.github/actions/artifactory-oidc | ||
|
|
||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.12" | ||
|
|
||
| - name: Validate tag matches package version | ||
| run: | | ||
| TAG="${GITHUB_REF#refs/tags/}" | ||
| # Strip leading 'v' if present | ||
| VERSION="${TAG#v}" | ||
| PKG_VERSION=$(python setup.py --version) | ||
| if [ "$VERSION" != "$PKG_VERSION" ]; then | ||
| echo "::error::Tag $TAG does not match setup.py version $PKG_VERSION" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Build package | ||
| run: | | ||
| pip install build | ||
| python -m build | ||
|
|
||
| - name: Verify package | ||
| run: | | ||
| pip install twine | ||
| twine check dist/* | ||
|
|
||
| - name: Publish to PyPI | ||
| uses: pypa/gh-action-pypi-publish@v1 |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,90 @@ | ||||||||||||||||||
| name: Test Release (Dry Run) | ||||||||||||||||||
|
|
||||||||||||||||||
| on: | ||||||||||||||||||
| workflow_dispatch: | ||||||||||||||||||
| inputs: | ||||||||||||||||||
| python-version: | ||||||||||||||||||
| description: "Python version to test with (or 'all' for full matrix)" | ||||||||||||||||||
| required: false | ||||||||||||||||||
| default: "3.12" | ||||||||||||||||||
|
|
||||||||||||||||||
| env: | ||||||||||||||||||
| ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }} | ||||||||||||||||||
|
|
||||||||||||||||||
| jobs: | ||||||||||||||||||
| test: | ||||||||||||||||||
| name: Test - Python ${{ matrix.python-version }} | ||||||||||||||||||
| runs-on: ${{ github.repository_owner == 'twilio-internal' && 'ubuntu-x64' || 'ubuntu-latest' }} | ||||||||||||||||||
| timeout-minutes: 20 | ||||||||||||||||||
| permissions: | ||||||||||||||||||
| contents: read | ||||||||||||||||||
| id-token: write | ||||||||||||||||||
| strategy: | ||||||||||||||||||
| fail-fast: false | ||||||||||||||||||
| matrix: | ||||||||||||||||||
| python-version: ${{ github.event.inputs.python-version == 'all' && fromJson('["3.8","3.9","3.10","3.11","3.12","3.13"]') || fromJson(format('["{0}"]', github.event.inputs.python-version)) }} | ||||||||||||||||||
| steps: | ||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||
| with: | ||||||||||||||||||
| fetch-depth: 0 | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Authenticate with Artifactory | ||||||||||||||||||
| uses: ./.github/actions/artifactory-oidc | ||||||||||||||||||
|
|
||||||||||||||||||
| - uses: actions/setup-python@v5 | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Semgrep identified an issue in your code: GitHub Actions step uses mutable version tag More details about thisThe step Attack scenario:
This mirrors real attacks like the 2023 trivy-action compromise, where a retagged version caused widespread supply-chain damage. Pin this to a specific commit SHA (e.g., To resolve this comment: ✨ Commit fix suggestion
Suggested change
View step-by-step instructions
💬 Ignore this findingReply with Semgrep commands to ignore this finding.
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag. Need help with this issue? Consult our appsec team or ask in #help-appsec on Slack. You can view more details about this finding in the Semgrep AppSec Platform. |
||||||||||||||||||
| with: | ||||||||||||||||||
| python-version: ${{ matrix.python-version }} | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Install dependencies | ||||||||||||||||||
| run: | | ||||||||||||||||||
| pip install virtualenv --upgrade | ||||||||||||||||||
| make install test-install | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Run tests | ||||||||||||||||||
| run: make test-with-coverage | ||||||||||||||||||
|
|
||||||||||||||||||
| deploy-dry-run: | ||||||||||||||||||
| name: Deploy (Dry Run - No Publish) | ||||||||||||||||||
| needs: [test] | ||||||||||||||||||
| runs-on: ${{ github.repository_owner == 'twilio-internal' && 'ubuntu-x64' || 'ubuntu-latest' }} | ||||||||||||||||||
| environment: pypi | ||||||||||||||||||
| permissions: | ||||||||||||||||||
| contents: read | ||||||||||||||||||
| id-token: write | ||||||||||||||||||
| attestations: write | ||||||||||||||||||
| steps: | ||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Semgrep identified an issue in your code: GitHub Actions step uses mutable version tag More details about thisThe Here's a concrete attack scenario:
The same risk applies to To resolve this comment: ✨ Commit fix suggestion
Suggested change
View step-by-step instructions
💬 Ignore this findingReply with Semgrep commands to ignore this finding.
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag. Need help with this issue? Consult our appsec team or ask in #help-appsec on Slack. You can view more details about this finding in the Semgrep AppSec Platform. |
||||||||||||||||||
|
|
||||||||||||||||||
| - name: Authenticate with Artifactory | ||||||||||||||||||
| uses: ./.github/actions/artifactory-oidc | ||||||||||||||||||
|
|
||||||||||||||||||
| - uses: actions/setup-python@v5 | ||||||||||||||||||
|
shrutiburman marked this conversation as resolved.
|
||||||||||||||||||
| with: | ||||||||||||||||||
| python-version: "3.12" | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Validate version in setup.py | ||||||||||||||||||
| run: | | ||||||||||||||||||
| PKG_VERSION=$(python setup.py --version) | ||||||||||||||||||
| echo "Package version: $PKG_VERSION" | ||||||||||||||||||
| echo "PKG_VERSION=$PKG_VERSION" >> "$GITHUB_ENV" | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Build package | ||||||||||||||||||
| run: | | ||||||||||||||||||
| pip install build | ||||||||||||||||||
| python -m build | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: Verify package | ||||||||||||||||||
| run: | | ||||||||||||||||||
| pip install twine | ||||||||||||||||||
| twine check dist/* | ||||||||||||||||||
|
|
||||||||||||||||||
| - name: List built artifacts | ||||||||||||||||||
| run: | | ||||||||||||||||||
| echo "Built artifacts:" | ||||||||||||||||||
| ls -lh dist/ | ||||||||||||||||||
| echo "" | ||||||||||||||||||
| echo "Package version: $PKG_VERSION" | ||||||||||||||||||
| echo "" | ||||||||||||||||||
| echo "--- DRY RUN COMPLETE ---" | ||||||||||||||||||
| echo "To publish for real, create a GitHub Release with a matching tag" | ||||||||||||||||||
| echo "and use the deploy.yml workflow." | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| pygments>=2.7.4 # not directly required, pinned by Snyk to avoid a vulnerability | ||
| requests>=2.32.2 | ||
| PyJWT>=2.0.0, <3.0.0 | ||
| aiohttp>=3.10.2 | ||
| aiohttp-retry==2.8.3 | ||
| certifi>=2023.7.22 # not directly required, pinned by Snyk to avoid a vulnerability | ||
| urllib3>=2.2.2 # not directly required, pinned by Snyk to avoid a vulnerability | ||
| zipp>=3.19.1 # not directly required, pinned by Snyk to avoid a vulnerability |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,54 @@ | ||
| pygments>=2.7.4 # not directly required, pinned by Snyk to avoid a vulnerability | ||
| requests>=2.32.2 | ||
| PyJWT>=2.0.0, <3.0.0 | ||
| aiohttp>=3.10.2 | ||
| # | ||
| # This file is autogenerated by pip-compile with Python 3.14 | ||
| # by the following command: | ||
| # | ||
| # pip-compile --output-file=requirements.txt requirements.in | ||
| # | ||
| aiohappyeyeballs==2.6.2 | ||
| # via aiohttp | ||
| aiohttp==3.14.1 | ||
| # via | ||
| # -r requirements.in | ||
| # aiohttp-retry | ||
| aiohttp-retry==2.8.3 | ||
| certifi>=2023.7.22 # not directly required, pinned by Snyk to avoid a vulnerability | ||
| urllib3>=2.2.2 # not directly required, pinned by Snyk to avoid a vulnerability | ||
| zipp>=3.19.1 # not directly required, pinned by Snyk to avoid a vulnerability | ||
| # via -r requirements.in | ||
| aiosignal==1.4.0 | ||
| # via aiohttp | ||
| attrs==26.1.0 | ||
| # via aiohttp | ||
| certifi==2026.5.20 | ||
| # via | ||
| # -r requirements.in | ||
| # requests | ||
| charset-normalizer==3.4.7 | ||
| # via requests | ||
| frozenlist==1.8.0 | ||
| # via | ||
| # aiohttp | ||
| # aiosignal | ||
| idna==3.18 | ||
| # via | ||
| # requests | ||
| # yarl | ||
| multidict==6.7.1 | ||
| # via | ||
| # aiohttp | ||
| # yarl | ||
| propcache==0.5.2 | ||
| # via | ||
| # aiohttp | ||
| # yarl | ||
| pygments==2.20.0 | ||
| # via -r requirements.in | ||
| pyjwt==2.13.0 | ||
| # via -r requirements.in | ||
| requests==2.34.2 | ||
| # via -r requirements.in | ||
| urllib3==2.7.0 | ||
| # via | ||
| # -r requirements.in | ||
| # requests | ||
| yarl==1.24.2 | ||
| # via aiohttp | ||
| zipp==4.1.0 | ||
| # via -r requirements.in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Semgrep identified an issue in your code:
Mutable version tag on
actions/checkout@v4could be silently updated to malicious code by an attacker who gains control of the repository, compromising your workflow execution.More details about this
The step uses
actions/checkout@v4, which pins to a mutable version tag instead of a specific commit SHA. An attacker who gains control of theactions/checkoutrepository could update thev4tag to point to malicious code. When your workflow runs, GitHub would automatically fetch and execute this compromised version without any notification.For example, if an attacker pushed malicious code to
actions/checkoutand moved thev4tag to that commit, the next time this workflow runs it would:uses: actions/checkout@v4stepfetch-depth: 0checkoutThis is a supply-chain attack vector that was exploited in real incidents like the trivy-action and kics-github-action compromises.
To resolve this comment:
✨ Commit fix suggestion
View step-by-step instructions
Replace the mutable GitHub Action tag with a full 40-character commit SHA in the
usesvalue.Change
actions/checkout@v4to a pinned commit such asactions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.Apply the same change to the other
actions/checkout@v4step in this workflow so both checkout steps use a commit SHA instead of a version tag.Keep the version comment after the SHA, for example
# v4, so the pinned action version is still easy to identify. Pinning to a commit SHA prevents the action owner from silently changing what code runs under the same tag.Leave the local action reference
uses: ./.github/actions/artifactory-oidcunchanged, because local actions are not pinned through remote Git references.💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasonsAlternatively, triage in Semgrep AppSec Platform to ignore the finding created by github-actions-mutable-action-tag.
Need help with this issue? Consult our appsec team or ask in #help-appsec on Slack.
You can view more details about this finding in the Semgrep AppSec Platform.