A GitHub Action for integrating CodeThreat security scanning into your CI/CD workflows. This action uses the CodeThreat CLI as a dependency, ensuring consistent behavior, faster execution, and better security. Results are automatically uploaded to GitHub's Security tab.
- 🚀 Dependency-Based Architecture: CLI imported as npm package (no external installation)
- 🔍 Comprehensive Security Scanning: SAST, SCA, Secrets, and IaC analysis
- 🤖 AI-Powered Analysis: False positive elimination and intelligent insights
- 📊 GitHub Integration: Automatic SARIF upload to GitHub Security tab
- ⚡ Fast & Secure: No network calls for CLI installation, always uses latest version
- 🛡️ Build Protection: Configurable failure conditions for CI/CD
- 📈 Detailed Reporting: Multiple output formats (SARIF, JSON, XML, CSV)
Add this action to your workflow:
name: Security Scanon: [push, pull_request]jobs:
security:
runs-on: ubuntu-latestpermissions:
security-events: write # Required for SARIF uploadcontents: readactions: readsteps:
- uses: actions/checkout@v4
- name: CodeThreat Security Scanuses: CodeThreat/codethreat-appsec-github-action@masterwith:
# Requiredapi-key: ${{ secrets.CODETHREAT_API_KEY }}server-url: ${{ secrets.CODETHREAT_SERVER_URL }}organization-slug: ${{ secrets.CODETHREAT_ORG_SLUG }}github-token: ${{ secrets.GITHUB_TOKEN }}# Optionalupload-sarif: truewait-for-completion: true| Input | Description | Example |
|---|---|---|
api-key | CodeThreat API key | ${{ secrets.CODETHREAT_API_KEY }} |
server-url | CodeThreat server URL | ${{ secrets.CODETHREAT_SERVER_URL }} |
organization-slug | Organization slug (from org settings) | ${{ secrets.CODETHREAT_ORG_SLUG }} |
| Input | Description | Default | Example |
|---|---|---|---|
repository-url | Repository URL to scan | Current repository | https://github.com/user/repo.git |
branch | Branch to scan | Current branch | main |
wait-for-completion | Wait for scan completion | true | false |
timeout | Scan timeout in seconds | 43200 (12 hours) | 7200 (2 hours) |
poll-interval | Status polling interval (seconds) | 30 | 60 |
output-format | Output format | sarif | json, csv, xml, junit |
output-file | Output file name | codethreat-results.sarif | security-report.json |
upload-sarif | Upload SARIF to GitHub Security | true | false |
fail-on-critical | Fail on critical vulnerabilities | false | true |
fail-on-high | Fail on high severity vulnerabilities | false | true |
max-violations | Max violations before failing | 0 (no limit) | 50 |
Note: By default, builds will not fail based on vulnerabilities. Set
fail-on-critical: trueorfail-on-high: trueto enforce security gates in your CI/CD pipeline. |skip-import| Skip import if repo exists |true|false| |verbose| Enable verbose logging |false|true|
Note: Scan types (SAST, SCA, Secrets, IaC) are automatically determined by your organization's configuration in CodeThreat. This ensures consistency across all CI/CD platforms.
| Output | Description |
|---|---|
scan-id | ID of the completed scan |
repository-id | ID of the imported repository |
results-file | Path to the results file |
violation-count | Total number of violations |
critical-count | Number of critical violations |
high-count | Number of high severity violations |
medium-count | Number of medium severity violations |
low-count | Number of low severity violations |
security-score | Security score (0-100) |
scan-duration | Scan duration in seconds |
scan-url | URL to view results in CodeThreat dashboard |
- name: CodeThreat Security Scanuses: CodeThreat/codethreat-appsec-github-action@masterwith:
# Requiredapi-key: ${{ secrets.CODETHREAT_API_KEY }}server-url: ${{ secrets.CODETHREAT_SERVER_URL }}github-token: ${{ secrets.GITHUB_TOKEN }}# Optionalscan-types: 'sast,sca,secrets'- name: CodeThreat Security Scanuses: CodeThreat/codethreat-appsec-github-action@masterwith:
# Requiredapi-key: ${{ secrets.CODETHREAT_API_KEY }}server-url: ${{ secrets.CODETHREAT_SERVER_URL }}github-token: ${{ secrets.GITHUB_TOKEN }}# Scan Configurationscan-types: 'sast,sca,secrets,iac'fail-on-critical: truefail-on-high: truemax-violations: 10timeout: 45# Output Configurationupload-sarif: trueoutput-format: 'sarif'verbose: true- name: CodeThreat Security Scanid: codethreatuses: CodeThreat/codethreat-appsec-github-action@masterwith:
# Requiredapi-key: ${{ secrets.CODETHREAT_API_KEY }}server-url: ${{ secrets.CODETHREAT_SERVER_URL }}github-token: ${{ secrets.GITHUB_TOKEN }}# Output Configurationoutput-format: 'json'output-file: 'security-report.json'upload-sarif: false
- name: Upload Custom Reportuses: actions/upload-artifact@v4with:
name: security-reportpath: security-report.json- name: CodeThreat Security Scanif: github.event_name == 'push' && github.ref == 'refs/heads/main'uses: CodeThreat/codethreat-appsec-github-action@masterwith:
api-key: ${{ secrets.CODETHREAT_API_KEY }}scan-types: 'sast,sca,secrets,iac'fail-on-critical: truefail-on-high: true- name: CodeThreat Security Scanid: security-scanuses: CodeThreat/codethreat-appsec-github-action@masterwith:
# Requiredapi-key: ${{ secrets.CODETHREAT_API_KEY }}server-url: ${{ secrets.CODETHREAT_SERVER_URL }}github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Comment on PRif: github.event_name == 'pull_request'uses: actions/github-script@v7with:
script: | const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, }); const scanResults = ` ## 🛡️ CodeThreat Security Scan Results - **Violations Found**: ${{ steps.security-scan.outputs.violation-count }} - **Critical**: ${{ steps.security-scan.outputs.critical-count }} - **High**: ${{ steps.security-scan.outputs.high-count }} - **Security Score**: ${{ steps.security-scan.outputs.security-score }}/100 [View Detailed Results](${{ steps.security-scan.outputs.scan-url }}) `; await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body: scanResults });- Sign up at CodeThreat
- Go to Organization Settings → API Keys
- Create a new API key with appropriate scopes
- Copy the API key
Go to your repository Settings → Secrets and variables → Actions, and add:
| Secret Name | Value | Description |
|---|---|---|
CODETHREAT_API_KEY | ctk_xxx... | Your CodeThreat API key |
CODETHREAT_SERVER_URL | https://app.codethreat.com | Server URL (optional) |
For SARIF upload to work, you need:
- Public repositories: GitHub Advanced Security is free
- Private repositories: Requires GitHub Advanced Security license
name: Security and Qualityon:
push:
branches: [main, develop]pull_request:
branches: [main]jobs:
security:
name: Security Scanruns-on: ubuntu-latestpermissions:
security-events: write # Required for SARIF uploadcontents: readsteps:
- name: Checkout Codeuses: actions/checkout@v4
- name: CodeThreat Security Scanuses: CodeThreat/codethreat-appsec-github-action@masterwith:
# Requiredapi-key: ${{ secrets.CODETHREAT_API_KEY }}server-url: ${{ secrets.CODETHREAT_SERVER_URL }}github-token: ${{ secrets.GITHUB_TOKEN }}# Configurationscan-types: 'sast,sca,secrets'fail-on-critical: truetimeout: 30verbose: ${{ runner.debug == '1' }}name: Multi-Environment Securityon: [push, pull_request]jobs:
security-dev:
if: github.ref != 'refs/heads/main'runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: CodeThreat/codethreat-appsec-github-action@masterwith:
api-key: ${{ secrets.CODETHREAT_DEV_API_KEY }}server-url: ${{ secrets.CODETHREAT_DEV_URL }}fail-on-critical: false # More lenient for developmentsecurity-prod:
if: github.ref == 'refs/heads/main'runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: CodeThreat/codethreat-appsec-github-action@masterwith:
api-key: ${{ secrets.CODETHREAT_PROD_API_KEY }}scan-types: 'sast,sca,secrets,iac'fail-on-critical: truefail-on-high: truemax-violations: 0# Zero tolerance for production"Authentication failed"
- Check that
CODETHREAT_API_KEYsecret is set correctly - Verify API key has not expired
- Ensure API key has required scopes
"SARIF upload failed"
- Enable GitHub Advanced Security for private repositories
- Check that workflow has
security-events: writepermission - Verify repository settings allow security uploads
"Scan timeout"
- Increase
timeoutvalue for large repositories - Check CodeThreat server status
- Consider running scan asynchronously with
wait-for-completion: false
Enable debug logging by adding to your workflow:
- name: CodeThreat Security Scanuses: CodeThreat/codethreat-appsec-github-action@masterwith:
# Requiredapi-key: ${{ secrets.CODETHREAT_API_KEY }}server-url: ${{ secrets.CODETHREAT_SERVER_URL }}github-token: ${{ secrets.GITHUB_TOKEN }}# Enable verbose loggingverbose: trueOr enable runner debug mode:
- Go to Actions → Re-run jobs → Enable debug logging
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
MIT License - see LICENSE file for details.