Skip to content

feat(mcp): support conversations in custom dispatchers #1350

feat(mcp): support conversations in custom dispatchers

feat(mcp): support conversations in custom dispatchers #1350

on:
pull_request:
merge_group:
name: Semgrep
permissions:
contents: read
env:
SEMGREP_ENABLE_VERSION_CHECK: 'false'
jobs:
# scans GitHub Actions and other repo-wide config
semgrep:
# This workflow runs org-wide as a required workflow. Private/internal repos
# get the faster Depot runner; public repos stay on GitHub-hosted ubuntu-latest
# (free minutes, and not every public repo has Depot enabled). The repository
# context reflects the target repo, so this resolves per-repo automatically.
runs-on: ${{ github.event.repository.private && 'depot-ubuntu-latest' || 'ubuntu-latest' }}
timeout-minutes: 15
container:
image: semgrep/semgrep:1.175.0@sha256:b94b53d02fd4a022f9eac4e2af1380f5c3c4c21400e79d3336bdff1d1db5e796
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
# Pull request scans compare the merge commit with its base parent.
# Fetch the parent so non-.github changes can skip the scan.
fetch-depth: 2
- name: Checkout .github repo (for custom semgrep rules)
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: PostHog/.github
path: dotgithub-repo
sparse-checkout: |
.semgrep
.github/scripts
- name: Check whether Semgrep must scan
id: check
env:
EVENT_NAME: ${{ github.event_name }}
run: |
if [ ! -d ".github/" ]; then
exit 0
fi
echo "exists=true" >> "$GITHUB_OUTPUT"
# The job container runs git as root, but the runner user owns the checkout, so git
# refuses the repo as "dubious ownership" and every check below falls through to a scan.
git config --global --add safe.directory "$GITHUB_WORKSPACE"
# The merge queue can combine several PRs, so it always gets full coverage.
if [ "$EVENT_NAME" != "pull_request" ] || ! git rev-parse --verify HEAD^1 >/dev/null 2>&1; then
echo "scan=true" >> "$GITHUB_OUTPUT"
exit 0
fi
if ! git diff --quiet HEAD^1 -- .github/; then
echo "scan=true" >> "$GITHUB_OUTPUT"
fi
- name: Run Semgrep
id: semgrep
if: steps.check.outputs.scan == 'true'
continue-on-error: true
run: |
# These upstream rules reparse every run block as Bash and reject valid GitHub expressions.
# Local generic-parser replacements preserve their coverage. Remove both exclusions and the
# replacements after https://github.com/semgrep/semgrep-rules/issues/3688 is fixed and the
# compatibility fixture passes with p/github-actions under --strict.
#
# --timeout raises semgrep's 5s per-rule-per-file default, which a contended
# GitHub-hosted runner trips on a large workflow file. Under --strict a rule
# timeout is an error, so that reds this required check across the org for a
# reason unrelated to the diff. 60s keeps the worst case (three rules hitting
# --timeout-threshold on one file) well inside the job's timeout-minutes.
#
# The trailofbits Ansible rules target playbook task keys, not workflow YAML. Each one binds
# every YAML key through metavariable-pattern, and semgrep evaluates each binding by writing
# it to a temp file, re-parsing it and deleting it behind a global lock. On large workflow
# files that filesystem work makes up almost all of the scan time, and on a slow runner it
# pushes the scan past timeout-minutes.
semgrep \
--config "dotgithub-repo/.semgrep/rules/" \
--config "p/owasp-top-ten" \
--config "p/security-audit" \
--config "p/trailofbits" \
--config "p/github-actions" \
--exclude-rule trailofbits.generic.curl-unencrypted-url.curl-unencrypted-url \
--exclude-rule dockerfile.security.no-sudo-in-dockerfile.no-sudo-in-dockerfile \
--exclude-rule trailofbits.generic.redis-unencrypted-transport.redis-unencrypted-transport \
--exclude-rule trailofbits.yaml.docker-compose.port-all-interfaces.port-all-interfaces \
--exclude-rule trailofbits.yaml.ansible.apt-key-unencrypted-url.apt-key-unencrypted-url \
--exclude-rule trailofbits.yaml.ansible.apt-key-validate-certs-disabled.apt-key-validate-certs-disabled \
--exclude-rule trailofbits.yaml.ansible.apt-unencrypted-url.apt-unencrypted-url \
--exclude-rule trailofbits.yaml.ansible.dnf-unencrypted-url.dnf-unencrypted-url \
--exclude-rule trailofbits.yaml.ansible.dnf-validate-certs-disabled.dnf-validate-certs-disabled \
--exclude-rule trailofbits.yaml.ansible.get-url-unencrypted-url.get-url-unencrypted-url \
--exclude-rule trailofbits.yaml.ansible.get-url-validate-certs-disabled.get-url-validate-certs-disabled \
--exclude-rule trailofbits.yaml.ansible.rpm-key-unencrypted-url.rpm-key-unencrypted-url \
--exclude-rule trailofbits.yaml.ansible.rpm-key-validate-certs-disabled.rpm-key-validate-certs-disabled \
--exclude-rule trailofbits.yaml.ansible.unarchive-unencrypted-url.unarchive-unencrypted-url \
--exclude-rule trailofbits.yaml.ansible.unarchive-validate-certs-disabled.unarchive-validate-certs-disabled \
--exclude-rule trailofbits.yaml.ansible.wrm-cert-validation-ignore.wrm-cert-validation-ignore \
--exclude-rule trailofbits.yaml.ansible.yum-unencrypted-url.yum-unencrypted-url \
--exclude-rule trailofbits.yaml.ansible.yum-validate-certs-disabled.yum-validate-certs-disabled \
--exclude-rule trailofbits.yaml.ansible.zypper-repository-unencrypted-url.zypper-repository-unencrypted-url \
--exclude-rule trailofbits.yaml.ansible.zypper-unencrypted-url.zypper-unencrypted-url \
--exclude-rule yaml.github-actions.security.audit.unsafe-add-mask-workflow-command.unsafe-add-mask-workflow-command \
--exclude-rule yaml.github-actions.security.curl-eval.curl-eval \
--exclude-rule yaml.github-actions.security.gha-curl-pipe-shell.gha-curl-pipe-shell \
--timeout 60 \
--error \
--strict \
--json-output "$RUNNER_TEMP/semgrep.json" \
--metrics=off \
--verbose \
.github/
- name: Report Semgrep results
if: always() && steps.semgrep.outcome != 'skipped'
env:
SEMGREP_OUTCOME: ${{ steps.semgrep.outcome }}
run: |
python3 dotgithub-repo/.github/scripts/report-semgrep-results.py "$RUNNER_TEMP/semgrep.json"
if [ "$SEMGREP_OUTCOME" != "success" ]; then
exit 1
fi