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 Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
permissions:
security-events: write # Required for SARIF upload
contents: read
actions: read
steps:
- uses: actions/checkout@v4
- name: CodeThreat Security Scan
uses: CodeThreat/codethreat-appsec-github-action@master
with:
# Required
api-key: ${{ secrets.CODETHREAT_API_KEY }}
server-url: ${{ secrets.CODETHREAT_SERVER_URL }}
organization-slug: ${{ secrets.CODETHREAT_ORG_SLUG }}
github-token: ${{ secrets.GITHUB_TOKEN }}
# Optional
upload-sarif: true
wait-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 Scan
uses: CodeThreat/codethreat-appsec-github-action@master
with:
# Required
api-key: ${{ secrets.CODETHREAT_API_KEY }}
server-url: ${{ secrets.CODETHREAT_SERVER_URL }}
github-token: ${{ secrets.GITHUB_TOKEN }}
# Optional
scan-types: 'sast,sca,secrets'- name: CodeThreat Security Scan
uses: CodeThreat/codethreat-appsec-github-action@master
with:
# Required
api-key: ${{ secrets.CODETHREAT_API_KEY }}
server-url: ${{ secrets.CODETHREAT_SERVER_URL }}
github-token: ${{ secrets.GITHUB_TOKEN }}
# Scan Configuration
scan-types: 'sast,sca,secrets,iac'
fail-on-critical: true
fail-on-high: true
max-violations: 10
timeout: 45
# Output Configuration
upload-sarif: true
output-format: 'sarif'
verbose: true- name: CodeThreat Security Scan
id: codethreat
uses: CodeThreat/codethreat-appsec-github-action@master
with:
# Required
api-key: ${{ secrets.CODETHREAT_API_KEY }}
server-url: ${{ secrets.CODETHREAT_SERVER_URL }}
github-token: ${{ secrets.GITHUB_TOKEN }}
# Output Configuration
output-format: 'json'
output-file: 'security-report.json'
upload-sarif: false
- name: Upload Custom Report
uses: actions/upload-artifact@v4
with:
name: security-report
path: security-report.json- name: CodeThreat Security Scan
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: CodeThreat/codethreat-appsec-github-action@master
with:
api-key: ${{ secrets.CODETHREAT_API_KEY }}
scan-types: 'sast,sca,secrets,iac'
fail-on-critical: true
fail-on-high: true- name: CodeThreat Security Scan
id: security-scan
uses: CodeThreat/codethreat-appsec-github-action@master
with:
# Required
api-key: ${{ secrets.CODETHREAT_API_KEY }}
server-url: ${{ secrets.CODETHREAT_SERVER_URL }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
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 Quality
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
security:
name: Security Scan
runs-on: ubuntu-latest
permissions:
security-events: write # Required for SARIF upload
contents: read
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: CodeThreat Security Scan
uses: CodeThreat/codethreat-appsec-github-action@master
with:
# Required
api-key: ${{ secrets.CODETHREAT_API_KEY }}
server-url: ${{ secrets.CODETHREAT_SERVER_URL }}
github-token: ${{ secrets.GITHUB_TOKEN }}
# Configuration
scan-types: 'sast,sca,secrets'
fail-on-critical: true
timeout: 30
verbose: ${{ runner.debug == '1' }}name: Multi-Environment Security
on: [push, pull_request]
jobs:
security-dev:
if: github.ref != 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: CodeThreat/codethreat-appsec-github-action@master
with:
api-key: ${{ secrets.CODETHREAT_DEV_API_KEY }}
server-url: ${{ secrets.CODETHREAT_DEV_URL }}
fail-on-critical: false # More lenient for development
security-prod:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: CodeThreat/codethreat-appsec-github-action@master
with:
api-key: ${{ secrets.CODETHREAT_PROD_API_KEY }}
scan-types: 'sast,sca,secrets,iac'
fail-on-critical: true
fail-on-high: true
max-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 Scan
uses: CodeThreat/codethreat-appsec-github-action@master
with:
# Required
api-key: ${{ secrets.CODETHREAT_API_KEY }}
server-url: ${{ secrets.CODETHREAT_SERVER_URL }}
github-token: ${{ secrets.GITHUB_TOKEN }}
# Enable verbose logging
verbose: 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.
- π Documentation
- π¬ Discord Community
- π§ Support Email
- π Report Issues