tc-scanner
v0.5.0
Published
CI security scanner and controls runner. Scan Dockerfiles, images, dependencies, and secrets. Run all security controls with one command.
Maintainers
Readme
tc-scanner
A CI security scanner for Dockerfiles, container images, dependencies, and secrets. Powered by Trivy.
Requirements
Docker is required. The scanner runs Trivy inside a container, so no additional installation is needed. All major CI platforms (Bitbucket Pipelines, GitHub Actions, GitLab CI) have Docker available by default.
Installation
No installation required. Use directly with npx:
npx tc-scanner scan ./DockerfileOr install globally:
npm install -g tc-scanner
tc-scan scan ./DockerfileQuick Start
# Scan a Dockerfile for misconfigurations
npx tc-scanner scan ./Dockerfile
# Scan project dependencies for known vulnerabilities
npx tc-scanner deps .
# Scan code for hardcoded secrets
npx tc-scanner secrets ./src
# Scan a container image
npx tc-scanner image nginx:latestCommands
scan - Dockerfile Security
Scans Dockerfiles for security misconfigurations.
npx tc-scanner scan ./Dockerfile
npx tc-scanner scan ./Dockerfile --severity HIGH
npx tc-scanner scan ./Dockerfile --output ./reports/dockerfile-scanWhat it detects:
- Running as root user
- Missing HEALTHCHECK instruction
- Using
latesttag instead of pinned versions - Insecure
ADDinstead ofCOPY - Exposed sensitive ports
- Missing USER instruction
deps - Dependency Vulnerabilities
Scans package lockfiles for known CVEs (similar to Snyk/npm audit).
npx tc-scanner deps .
npx tc-scanner deps ./backend --severity CRITICAL
npx tc-scanner deps . --include-devSupported lockfiles:
package-lock.json(npm)yarn.lock(Yarn)pnpm-lock.yaml(pnpm)Gemfile.lock(Ruby)requirements.txt/Pipfile.lock(Python)go.sum(Go)composer.lock(PHP)pom.xml(Maven / Java, Kotlin)
secrets - Secret Detection
Scans code for hardcoded secrets and sensitive data.
npx tc-scanner secrets .
npx tc-scanner secrets ./src --output ./reports/secretsWhat it detects:
- AWS access keys and secrets
- API tokens (Stripe, GitHub, Slack, etc.)
- Private keys (RSA, SSH, PGP)
- Database connection strings
- Hardcoded passwords
- JWT secrets
image - Container Image Scanning
Scans container images for OS and application vulnerabilities.
npx tc-scanner image nginx:latest
npx tc-scanner image myapp:v1.2.3 --severity HIGH,CRITICALWhat it detects:
- OS package vulnerabilities (Alpine, Debian, Ubuntu, RHEL, etc.)
- Application dependencies inside the image
- Embedded secrets and misconfigurations
Options
| Option | Alias | Description | Default |
| --------------- | ----- | ----------------------------------------------------------- | ------- |
| --severity | -s | Minimum severity level: LOW, MEDIUM, HIGH, CRITICAL | HIGH |
| --output | -o | Save reports to file (creates .json, .txt, .html) | - |
| --webhook | -w | Send results to a webhook URL | - |
| --exit-code | - | Exit code when issues are found | 1 |
| --include-dev | - | Include dev dependencies (deps command only) | false |
Reports
Generate reports in multiple formats:
npx tc-scanner scan ./Dockerfile --output ./reports/scan-reportThis creates:
scan-report.json- Structured data for APIs and integrationsscan-report.txt- Plain text for email notificationsscan-report.html- Styled HTML report for attachments
Webhooks
Send scan results to any webhook endpoint:
# Generic webhook
npx tc-scanner scan ./Dockerfile --webhook https://your-api.com/security-alerts
# Slack incoming webhook
npx tc-scanner scan ./Dockerfile --webhook https://hooks.slack.com/services/xxx/yyy/zzzWebhook payload:
{
"scanner": "tc-scanner",
"scanType": "dockerfile",
"timestamp": "2024-01-15T10:30:00.000Z",
"target": "./Dockerfile",
"summary": {
"total": 3,
"critical": 0,
"high": 1,
"medium": 2,
"low": 0
},
"issues": [
{
"id": "DS-0002",
"severity": "HIGH",
"title": "Last USER command should not be 'root'",
"description": "Running containers with 'root' user can lead to container escape.",
"url": "https://avd.aquasec.com/misconfig/ds-0002"
}
]
}CI/CD Integration
Bitbucket Pipelines
image: node:20
definitions:
services:
docker:
memory: 2048
pipelines:
default:
- step:
name: Security Scan
services:
- docker
script:
- npx tc-scanner scan ./Dockerfile --severity HIGH
- npx tc-scanner deps . --severity HIGH
# Send results to Slack or custom webhook
- npx tc-scanner scan ./Dockerfile --webhook $SECURITY_WEBHOOK_URL --exit-code 0
pull-requests:
"**":
- step:
name: PR Security Check
services:
- docker
script:
- npx tc-scanner scan ./Dockerfile --severity CRITICAL
- npx tc-scanner secrets ./srcNote: Add
SECURITY_WEBHOOK_URLas a repository variable in Bitbucket settings for webhook notifications.
Bitbucket Pipelines — Java / Maven (Kotlin)
image: eclipse-temurin:17
definitions:
services:
docker:
memory: 2048
pipelines:
default:
- step:
name: TC-Secure Controls (Maven)
services:
- docker
caches:
- maven
script:
# Auto-detects maven stack from pom.xml and runs all 5 controls
- npx tc-scanner controls .
--base-url $TC_ADMIN_BASE_URL
--api-key $SERVICE_API_KEY
--client-name $CLIENT_NAME
pull-requests:
"**":
- step:
name: PR Security Check (Maven)
services:
- docker
caches:
- maven
script:
- npx tc-scanner controls . --controls 1,2,3 --dry-runJaCoCo coverage: to get real line-coverage numbers in control 7, add the JaCoCo Maven plugin to your
pom.xmland run./mvnw verifyinstead of./mvnw testso thattarget/site/jacoco/jacoco.xmlis generated before the scanner reads it.
GitHub Actions
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Scan Dockerfile
run: npx tc-scanner scan ./Dockerfile --severity HIGH
- name: Scan Dependencies
run: npx tc-scanner deps . --severity HIGH
- name: Scan for Secrets
run: npx tc-scanner secrets ./srcGitLab CI
security-scan:
image: node:20
services:
- docker:dind
variables:
DOCKER_HOST: tcp://docker:2375
script:
- npx tc-scanner scan ./Dockerfile --severity HIGH
- npx tc-scanner deps . --severity HIGH
- npx tc-scanner secrets ./src
artifacts:
paths:
- reports/
when: alwaysControls Platform Integration (tc-admin)
For normalized control ingestion into tc-admin, use:
- emitter script:
./scripts/emit-check-run.mjs - pipeline template:
./examples/bitbucket-pipelines.controls.example.yml
Required CI variables:
TC_ADMIN_BASE_URL(example:https://tc-admin.internal)SERVICE_API_KEY(shared ingest key)CLIENT_NAME(tenant/client label)
Quality-gate readiness check:
# Human-readable readiness output
npx tc-scanner quality-gate . --ci-provider bitbucket
# JSON output for automation
npx tc-scanner quality-gate . --ci-provider bitbucket --json
# Fail CI when gate is not enabled
npx tc-scanner quality-gate . --ci-provider bitbucket --strictThe check inspects:
- Presence of
bitbucket-pipelines.yml - Control pipeline signals (e.g.
tc-scan controls, emit script, scan/test commands) - Required ingestion env vars (
TC_ADMIN_BASE_URL,SERVICE_API_KEY,CLIENT_NAME)
The template posts these control codes:
SEC_DEP_PATCHSEC_CONTAINER_VULNSEC_SECRETSCODE_STATICQA_TESTS
Supported stacks (auto-detected from project files):
| Stack | Detected by | Control 1 | Control 4 | Control 7 |
| -------- | ------------------------------------ | ------------------------- | --------------------------- | ------------------------------------- |
| node | package.json, lockfiles | npm/pnpm audit | lint/typecheck scripts | test script + coverage-summary.json |
| python | requirements.txt, pyproject.toml | pip-audit | ruff/pyright/mypy | pytest |
| php | composer.json | composer audit | composer run lint/phpstan | composer run test |
| maven | pom.xml | Trivy filesystem CVE scan | ./mvnw test-compile | ./mvnw test + Surefire + JaCoCo |
Force a specific stack with --stack maven if auto-detection is ambiguous.
Maven / Java / Kotlin notes:
- Control 1 uses Trivy's filesystem scanner to match
pom.xmldependencies against the CVE database — no Maven execution needed. If nativetrivyis unavailable, the scanner automatically falls back to Docker-based Trivy. - Control 3 (Secrets) runs a repository scan first; for Maven projects with a
pom.xml, it also performs a focusedpom.xmlsecret scan when the repository-level result is empty. - Control 4 runs
./mvnw test-compile -B -q(falls back to systemmvnif no wrapper is present). Compile errors are reported aslint_errors. - You can override Control 4 for Maven in
_tc-scan.config.jsonwithcontrols.static.lint_command(and optionalcontrols.static.cwd) to run project-specific quality goals. - Control 7 runs
./mvnw test -Band parsestarget/surefire-reports/TEST-*.xmlfor accurate pass/fail counts. Line coverage is read fromtarget/site/jacoco/jacoco.xmlwhen present (requires the JaCoCo Maven plugin); otherwisecoverage_pctfalls back topass_rate_pct. - The Maven wrapper (
mvnw) is preferred over a system-installedmvnwhen present in the project root.
Exit Codes
| Code | Meaning |
| ---- | --------------------------------------------- |
| 0 | No issues found (or below severity threshold) |
| 1 | Issues found at or above severity threshold |
Use --exit-code 0 to always pass (useful for non-blocking scans):
npx tc-scanner scan ./Dockerfile --exit-code 0Severity Levels
| Level | Description |
| ---------- | --------------------------------------------------- |
| CRITICAL | Severe vulnerabilities requiring immediate action |
| HIGH | Important security issues that should be fixed soon |
| MEDIUM | Moderate issues to address in regular maintenance |
| LOW | Minor issues or best practice recommendations |
Examples
Fail CI only on critical issues:
npx tc-scanner scan ./Dockerfile --severity CRITICALFull security audit with reports:
npx tc-scanner scan ./Dockerfile --output ./reports/dockerfile --severity LOW
npx tc-scanner deps . --output ./reports/deps --severity LOW --include-dev
npx tc-scanner secrets ./src --output ./reports/secretsSend alerts to Slack on failures:
npx tc-scanner scan ./Dockerfile --webhook $SLACK_WEBHOOK_URLTroubleshooting
"Docker is required"
- Ensure Docker is installed and running
- In CI, enable the Docker service (see examples above)
"No lockfile found" (deps command)
- The scanner needs
package-lock.json,yarn.lock,pom.xml, or similar - Run
npm install(Node) or ensurepom.xmlis present (Maven) to enable scanning
Maven build fails during control 4 or 7
- Ensure JDK 17+ is available in the CI image (e.g.
eclipse-temurin:17) - The scanner prefers
./mvnwover a systemmvn; commit the Maven wrapper to your repo - For coverage data, add the JaCoCo plugin and run
./mvnw verifyto producetarget/site/jacoco/jacoco.xml
Slow first run
- First run downloads the Trivy Docker image (~50MB) and vulnerability database (~80MB)
- Subsequent runs are faster due to caching
