feat(replay-vision): API validation + lens_result row column #139885
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| on: | |
| push: | |
| branches: | |
| - master | |
| pull_request: | |
| merge_group: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| name: Security | |
| permissions: | |
| contents: read | |
| env: | |
| SEMGREP_ENABLE_VERSION_CHECK: 'false' | |
| jobs: | |
| ensure-pinned-actions: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Ensure SHA pinned actions | |
| uses: zgosalvez/github-actions-ensure-sha-pinned-actions@6124774845927d14c601359ab8138699fa5b70c3 # v4.0.1 | |
| with: | |
| allowlist: | | |
| actions/ | |
| github/ | |
| PostHog/ | |
| semgrep-python: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Run Semgrep | |
| run: | | |
| semgrep \ | |
| --config "p/python" \ | |
| --config "p/owasp-top-ten" \ | |
| --config "p/security-audit" \ | |
| --config "p/trailofbits" \ | |
| --config ".semgrep/rules" \ | |
| --exclude-rule trailofbits.generic.redis-unencrypted-transport.redis-unencrypted-transport \ | |
| --exclude-rule "python.django.security.audit.csrf-exempt.no-csrf-exempt" \ | |
| --exclude-rule "generic.html-templates.security.var-in-href.var-in-href" \ | |
| --error \ | |
| --metrics=off \ | |
| --verbose \ | |
| common/ ee/ frontend/ posthog/ products/ services/llm-gateway/ services/stripe-mock/ | |
| semgrep-go: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Run Semgrep | |
| run: | | |
| semgrep \ | |
| --config "p/golang" \ | |
| --config "p/owasp-top-ten" \ | |
| --config "p/security-audit" \ | |
| --config "p/trailofbits" \ | |
| --config "r/go.lang.security" \ | |
| --exclude-rule go.lang.security.audit.xss.no-fprintf-to-responsewriter.no-fprintf-to-responsewriter \ | |
| --error \ | |
| --metrics=off \ | |
| --verbose \ | |
| livestream/ | |
| semgrep-rust: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Run Semgrep | |
| run: | | |
| semgrep \ | |
| --config "p/rust" \ | |
| --config "p/owasp-top-ten" \ | |
| --config "p/security-audit" \ | |
| --config "p/trailofbits" \ | |
| --config "r/rust.lang.security" \ | |
| --exclude-rule trailofbits.generic.curl-unencrypted-url.curl-unencrypted-url \ | |
| --exclude-rule trailofbits.generic.redis-unencrypted-transport.redis-unencrypted-transport \ | |
| --exclude-rule trailofbits.rs.panic-in-function-returning-result.panic-in-function-returning-result \ | |
| --error \ | |
| --metrics=off \ | |
| --verbose \ | |
| cli/ rust/ | |
| semgrep-js: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Run Semgrep | |
| run: | | |
| semgrep \ | |
| --config ".semgrep/rules/" \ | |
| --config "p/javascript" \ | |
| --config "p/owasp-top-ten" \ | |
| --config "p/security-audit" \ | |
| --config "p/trailofbits" \ | |
| --error \ | |
| --metrics=off \ | |
| --verbose \ | |
| frontend/ nodejs/ services/mcp/ services/oauth-proxy/ services/stripe-app/ | |
| semgrep-products-frontend: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| # Single-rule scan — keeps the failure surface here aligned with the | |
| # job name. Other custom TS rules (no-direct-fuse-instantiation, | |
| # require-iframe-sandbox, ...) live in semgrep-js. When more | |
| # product-specific rules land, extend the --config list explicitly. | |
| - name: Run Semgrep | |
| run: | | |
| semgrep \ | |
| --config ".semgrep/rules/prefer-codegen-api.yaml" \ | |
| --error \ | |
| --metrics=off \ | |
| --verbose \ | |
| products/ | |
| # scans GitHub Actions and other repo-wide config | |
| semgrep-general: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| # exclude all directories already scanned by other jobs | |
| - name: Run Semgrep | |
| run: | | |
| semgrep \ | |
| --config "p/owasp-top-ten" \ | |
| --config "p/security-audit" \ | |
| --config "p/trailofbits" \ | |
| --config "p/github-actions" \ | |
| --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 \ | |
| --error \ | |
| --metrics=off \ | |
| --verbose \ | |
| --exclude ./cli/ \ | |
| --exclude ./common/ \ | |
| --exclude ./ee/ \ | |
| --exclude ./frontend/ \ | |
| --exclude ./livestream/ \ | |
| --exclude ./nodejs/ \ | |
| --exclude ./posthog/ \ | |
| --exclude ./products/ \ | |
| --exclude ./rust/ \ | |
| --exclude ./.semgrep/ \ | |
| --exclude ./docs/ \ | |
| --exclude ./services/ \ | |
| . | |
| # Devex / hygiene rules. Two passes: | |
| # - WARNING-severity rules print findings without failing the job | |
| # (used while migrating away from a pattern with a known backlog). | |
| # - ERROR-severity rules fail the job on any finding (regression guards). | |
| # See `.semgrep/devex-rules/README.md`. | |
| semgrep-devex: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| # Pass 1: print WARNING-severity findings. No --error — this step | |
| # does not fail CI. Backlogs from migration-in-progress rules show | |
| # up here. | |
| - name: Warnings (informational) | |
| run: | | |
| semgrep \ | |
| --config ".semgrep/devex-rules/" \ | |
| --severity=WARNING \ | |
| --metrics=off \ | |
| --verbose \ | |
| common/ ee/ frontend/ posthog/ products/ | |
| # Pass 2: enforce ERROR-severity rules. Any finding fails the | |
| # job — regression guards live here. | |
| - name: Errors (blocking) | |
| run: | | |
| semgrep \ | |
| --config ".semgrep/devex-rules/" \ | |
| --severity=ERROR \ | |
| --error \ | |
| --metrics=off \ | |
| --verbose \ | |
| common/ ee/ frontend/ posthog/ products/ | |
| semgrep-test-rules: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Test custom Semgrep rules | |
| run: | | |
| semgrep --test .semgrep/ | |
| semgrep_checks: | |
| needs: | |
| - semgrep-python | |
| - semgrep-go | |
| - semgrep-rust | |
| - semgrep-js | |
| - semgrep-products-frontend | |
| - semgrep-general | |
| - semgrep-devex | |
| - semgrep-test-rules | |
| name: Semgrep Checks Pass | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| if: always() | |
| steps: | |
| - name: Check matrix outcome | |
| run: | | |
| if [[ "${{ needs.semgrep-python.result }}" != "success" && "${{ needs.semgrep-python.result }}" != "skipped" ]]; then | |
| echo "semgrep-python did not complete successfully." | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.semgrep-go.result }}" != "success" && "${{ needs.semgrep-go.result }}" != "skipped" ]]; then | |
| echo "semgrep-go did not complete successfully." | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.semgrep-rust.result }}" != "success" && "${{ needs.semgrep-rust.result }}" != "skipped" ]]; then | |
| echo "semgrep-rust did not complete successfully." | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.semgrep-js.result }}" != "success" && "${{ needs.semgrep-js.result }}" != "skipped" ]]; then | |
| echo "semgrep-js did not complete successfully." | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.semgrep-products-frontend.result }}" != "success" && "${{ needs.semgrep-products-frontend.result }}" != "skipped" ]]; then | |
| echo "semgrep-products-frontend did not complete successfully." | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.semgrep-general.result }}" != "success" && "${{ needs.semgrep-general.result }}" != "skipped" ]]; then | |
| echo "semgrep-general did not complete successfully." | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.semgrep-devex.result }}" != "success" && "${{ needs.semgrep-devex.result }}" != "skipped" ]]; then | |
| echo "semgrep-devex did not complete successfully." | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.semgrep-test-rules.result }}" != "success" && "${{ needs.semgrep-test-rules.result }}" != "skipped" ]]; then | |
| echo "semgrep-test-rules did not complete successfully." | |
| exit 1 | |
| fi | |
| echo "All checks passed." |