I've been integrating Checkmarx One into our Jenkins pipeline and occasionally hit scan failures where the engine's generic error message is insufficient for root-cause analysis. Specifically, when a scan aborts with `Engine Error` or times out, the default logs lack the granularity needed to debug network, resource, or policy issues.
Based on my experience and the documentation, enabling detailed logging requires setting specific environment variables for the scan engine process. The exact method depends on your integration method (CLI, Jenkins plugin, GitHub Action). Here are the most effective approaches:
**For the Checkmarx CLI (`cx scan`)**:
- Set `CX_LOG_LEVEL=DEBUG` before running the scan command. This increases verbosity for the CLI itself.
- For the underlying engine, use `CX_ENGINE_LOG_LEVEL=DEBUG`. This is often the key to seeing engine startup, communication, and timeout details.
- Example in a shell step:
```bash
export CX_ENGINE_LOG_LEVEL=DEBUG
export CX_LOG_LEVEL=DEBUG
cx scan create ... [your parameters]
```
**In a Jenkins Pipeline** (using the `checkmarxScan` step):
Pass these as environment variables to the step's context. You may need to set them in the `script` block preceding the scan step.
```groovy
environment {
CX_ENGINE_LOG_LEVEL = 'DEBUG'
}
steps {
checkmarxScan(
// ... your configuration
)
}
```
**Important Considerations**:
- Debug logs can be verbose and may contain sensitive data. Redirect output to a file for analysis and avoid exposing them in public CI logs.
- For containerized engines, ensure the environment variable is passed to the container runtime.
- If the issue is network-related, also consider using `CX_HTTP_PROXY` and related proxy variables, which can be logged in more detail with the debug level.
After implementing this, look for log entries related to `EngineInvoker`, `CxEngineClient`, and `ScanManager`. They typically reveal connection handshakes, download progress for the engine, and policy evaluation steps.
Has anyone found additional engine-specific flags or config files that provide even deeper insight, perhaps into memory allocation or thread pooling during the scan phase?
--crusader
Commit early, deploy often, but always rollback-ready.
Been down this road. Those debug env vars help, but half the time the engine logs just vanish when it crashes hard.
If you're running in Jenkins, make sure you capture the job's console output raw. The plugin sometimes swallows the good bits. I've had to ditch the plugin and call the CLI directly in a shell step to get the full stream.
Also, good luck getting anything useful on a timeout. Usually it's a resource issue on their end, and the logs just stop.
CRM is a necessary evil
Totally agree about ditching the plugin for direct CLI calls - that's been a lifesaver for me. The plugin's abstraction layer just adds another point of failure when you need raw logs.
One extra step that's saved me: I pipe the CLI output to a timestamped file in the workspace *and* let Jenkins capture the console. That way, if Jenkins truncates, I've still got the full artifact. Something like `CX_LOG_LEVEL=DEBUG cx scan ... 2>&1 | tee scan_debug_$(date +%s).log`.
You're right that timeouts are often a black box. I've started adding a pre-scan resource check script to at least rule out our own environment before blaming their end.
Automate everything.
Piping to a timestamped file with `tee` is such a solid move. I've had Jenkins' console output buffer fail me right at the worst moment, leaving me with half a log.
One caveat I'd add - if you're on a resource-constrained node, watch out for disk space when you keep all those debug logs. I set up a post-build step to clean up files older than 5 runs, or compress them, just to avoid a silent failure from a full disk later.
That pre-scan resource check is brilliant. Did you build that internally, or is there a community script you're using? I'd love to see what metrics you're checking against.
Pipeline is king.
Good summary of the variable setup. The one I often see missed is that you need both `CX_LOG_LEVEL` and `CX_ENGINE_LOG_LEVEL` set together for the full picture - the CLI and the engine produce separate streams. Also, for the Jenkins plugin specifically, you have to inject those env vars into the step's execution context, which can be tricky if you're using a declarative pipeline.
A quick addition: if you're using the CLI in a containerized environment (like a Docker agent), remember those environment variables need to be passed into the container, not just set on the host node.
Keep it constructive.
That's an excellent distinction regarding the dual logging streams. I've found that missing `CX_ENGINE_LOG_LEVEL` often leaves you blind to the actual scan session initialization and communication with the SaaS backend, which is where many timeouts originate.
Your point about containerized environments is critical. In my Jenkins declarative pipelines, I had to explicitly pass the environment block into the `container` definition, like so:
```groovy
container('cx-cli') {
environment {
CX_ENGINE_LOG_LEVEL = 'DEBUG'
CX_LOG_LEVEL = 'DEBUG'
}
sh 'cx scan ...'
}
```
Without that, the container runs with its default environment, and the host's Jenkins environment is ignored. This tripped me up for longer than I'd care to admit.
—KH