A comprehensive TeamCity plugin that integrates MetaDefender Software Supply Chain security scanning into your CI/CD pipelines, providing automated vulnerability detection, malware scanning, secret detection, and license compliance checking.
- TeamCity Server: 2020.1 or later
- Java Development Kit: JDK 8 or later (full JDK is required; a standalone JRE will fail the build)
- OPSWAT MDSSC Account: Active subscription with API access
- Git Repository: Configured in MDSSC workflow
Linux / macOS:
# Standard build
./gradlew clean build
# Using specific JDK (if needed)
JAVA_HOME=/path/to/jdk ./gradlew clean buildWindows (PowerShell):
# Standard build
.\gradlew.bat clean build
# Using specific JDK temporarily for this invocation
$env:JAVA_HOME='C:\\Java\\jdk-17'; .\gradlew.bat clean buildTip: after setting JAVA_HOME, run java -version to confirm the shell is using your chosen JDK.
The packaged server plugin (bundles the agent automatically) will be created at a path like:
gradle-runner-server/build/distributions/OPSWAT-MDSSC-v<version>.zip
Example for version 2.0.0:
gradle-runner-server/build/distributions/OPSWAT-MDSSC-v2.0.0.zip
For reference, the standalone agent zip is placed at:
gradle-runner-agent/build/distributions/OPSWAT-MDSSC-v<version>.zip
- Navigate to TeamCity Administration → Plugins
- Click Upload plugin zip
- Select the
OPSWAT-MDSSC-v<version>.zipfile - Restart TeamCity server
- Verify plugin appears in installed plugins list
- Go to your project build configuration
- Click Add build step
- Select MetaDefender Software Supply Chain (runner type ID:
opswat-mdssc-scanner)
- MDSSC Webhook URL: Your OPSWAT webhook endpoint
- MDSSC API Key: Your OPSWAT API key
- Fail build on vulnerability severity: Choose minimum severity level to fail builds (default: high). Build will always fail on threats, secrets, or blocked licenses regardless of this threshold.
Tip: Store the API key as a secure TeamCity parameter (e.g. secure:opswat.api.key) and reference it in the build step instead of plain text.
<teamcity-server>/bin/teamcity-server.sh start
<teamcity-server>/bin/teamcity-server.sh stop
<teamcity-server>/bin/teamcity-server.sh restart# View server logs
tail -f <teamcity-data>/logs/teamcity-server.log
# Monitor agent logs
tail -f <teamcity-agent>/logs/teamcity-agent.logteamcity-gradle/
├── gradle-runner-agent/ # Agent-side plugin logic
│ └── src/main/java/jetbrains/buildServer/gradle/agent/
│ ├── GradleRunnerService.java # Main execution engine
│ ├── ConfigurationParamsUtil.java # Parameter handling
│ ├── GradleRunnerServiceFactory.java # Service factory
│ └── WebhookUrlParser.java # URL parsing
├── gradle-runner-server/ # Server-side plugin logic
│ └── src/main/java/jetbrains/buildServer/gradle/server/
│ └── GradleRunType.java # Plugin registration
├── gradle-runner-common/ # Shared components
│ └── src/main/java/jetbrains/buildServer/gradle/
│ └── GradleRunnerConstants.java # Constants
├── build.gradle # Main build configuration
├── settings.gradle # Gradle settings
└── README.md
Key Methods:
makeProgramCommandLine() // Plugin entry point
logSecurityScanningConfiguration() // Configuration validation
getRepositoryIdFromWorkflow() // MDSSC API workflow integration
getPossibleRepositoryNames() // Multi-provider name generation
monitorScanProgress() // Real-time scan tracking
processScanResults() // Security analysis and reportingPurpose: Build parameter extraction and validation
getWebhookUrl() // Extract webhook URL
getApiKey() // Extract API key
getFailBuildOnSeverity() // Extract severity thresholdPurpose: Server-side plugin registration and UI integration
getType() // Plugin identifier
getDisplayName() // UI display name
describeParameters() // Parameter descriptions| Component | Log Location |
|---|---|
| TeamCity Server | <teamcity-data>/logs/teamcity-server.log |
| TeamCity Agent | <teamcity-agent>/logs/teamcity-agent.log |
| Build Logs | TeamCity web interface → Build → Build Log |
| Plugin Debug | Search for MDSSC scan or MetaDefender Software Supply Chain in logs |
- Runner type ID (stable automation key):
opswat-mdssc-scanner - Parameter keys:
ui.gradleRunner.security.webhook.urlui.gradleRunner.security.api.keyui.gradleRunner.security.fail.on.severity
- Archive naming:
OPSWAT-MDSSC-v<version>.zip
These identifiers are stable and should not be changed once users start scripting Kotlin DSL or REST API configurations.
If using the bundled DSL extension you can add a step:
steps {
opswatSoftwareSupplyChainScanner {
name = "OPSWAT Security Scan"
webhookUrl = "%secure:opswat.webhook%"
apiKey = "%secure:opswat.api.key%"
failOnSeverity = "high" // low|medium|high|critical|off
}
}| Symptom | Possible Cause | Action |
|---|---|---|
| Step instantly succeeds without scanning | Missing webhook URL | Provide valid MDSSC webhook URL |
| Build never fails despite vulnerabilities | Severity threshold set too high or off |
Lower threshold (e.g. medium) |
| Long delay after scan completes | Intentional 60s post-completion wait (TODO in code) | Safe to ignore; will be optimized in future |
Windows agent error running echo |
Shell command resolution issue | Replace runtime command with cross-platform stub (future improvement) |
For deeper debugging enable verbose logging on the agent and search for MDSSC workflow or MDSSC scan lines.