Example Output

Sample Secret Discovery

{
  "result_type": "scan",
  "plugin_id": "qualys-container-security-plugin",
  "plugin_version": "1.1.0.dev",
  "data": {
    "type": "secret",
    "timestamp": "2026-03-12T16:50:13-04:00",
    "urn": "urn:secret:name:GitHub Personal Access Token:2f1f1810aa3ee99d340e8b17b41048120374934de6a0aaa6313c6b31f8a926ce:app/.env:2",
    "url": "https://558162184545.dkr.ecr.us-east-1.amazonaws.com/entrust-discovery-test:latest#app/.env",
    "extra": {
      "category": "Github",
      "name": "GitHub Personal Access Token",
      "severity": "critical",
      "file_path": "app/.env",
      "layer_sha": "2f1f1810aa3ee99d340e8b17b41048120374934de6a0aaa6313c6b31f8a926ce",
      "rule_uuid": "d3fa61b2-c95f-11ed-afa1-0242ac120002",
      "last_modified_date": "2026-03-12T16:49:55-04:00",
      "start_line": 2
    }
  }
}

Incremental Scanning

This plugin currently supports full scans only.

You may include a state object for plugin-runner compatibility:

{
  "config": {
    "username": "your-username",
    "password": "your-password",
    "gatewayUrl": "https://gateway.qg3.apps.qualys.com"
  },
  "state": {
    "lastRunDateTime": ""
  }
}

If state.lastRunDateTime is non-empty, the plugin returns a state error:

  • incremental scans not supported currently

To run scans successfully, either omit state or set lastRunDateTime to an empty value.

Troubleshooting

Authentication Failures

Error: "authentication failed" or HTTP 401

Causes:

  • Invalid username or password
  • User permissions insufficient (missing Container Security role)
  • Gateway URL incorrect or unreachable
  • Account locked or disabled

Solutions:

  1. Verify username and password in Qualys console
  2. Confirm Container Security module is active in your subscription
  3. Check user has "ContainerSecurity - User" role (or higher)
  4. Verify gateway URL matches your region
  5. Test connectivity: ping <gateway-hostname>
  6. Check firewall rules allow HTTPS (443) to Qualys gateway

Connection Timeouts

Error: "connection refused" or "i/o timeout"

Causes:

  • Network connectivity issues
  • Gateway URL unreachable
  • Firewall/proxy blocking HTTPS
  • Qualys API service unavailable

Solutions:

  1. Test connectivity to gateway: curl -I https://<gateway-url>
  2. Verify firewall allows outbound HTTPS (port 443)
  3. Check proxy settings if behind corporate proxy
  4. Try a different network connection to rule out ISP blocks
  5. Contact Qualys support to check service status

No Secrets Discovered

Possible Causes:

  • No container images configured in Qualys Container Security
  • Images don't contain detectable secrets
  • User permissions don't include Container Security
  • Container Security module not active

Solutions:

  1. Log into Qualys console and verify images are listed in Container Security
  2. Test with known image containing secrets for validation
  3. Confirm Container Security module is visible in Qualys console
  4. Check user permissions in Qualys (needs Container Security role)
  5. Verify API token generation is allowed for user account

API Errors

Error: "list request failed" or HTTP 400/404 errors

Causes:

  • API endpoint unavailable or changed
  • Qualys API version mismatch
  • Gateway URL incorrect
  • API rate limiting

Solutions:

  1. Verify gateway URL is correct for your region
  2. Check Qualys Container Security API documentation version matches plugin
  3. Review plugin logs for detailed API error messages
  4. If rate limited, wait and retry after delay
  5. Contact Qualys support with error details

Building the Plugin

Standard Build

make build

Creates executable: qualys-container-security-plugin

Build with Custom Version

go build -ldflags "-X main.Version=1.2.3" -o qualys-container-security-plugin

Testing

Run Unit Tests

make test

Runs unit tests only (skips integration tests due to -short flag).

Run Integration Tests

make integration-test

Runs full test suite including integration tests against a mock Qualys server.

Requirements for Integration Tests:

  • Go 1.25.7+ installed
  • git, make available
  • No specific Qualys credentials needed (uses mock server)

For detailed integration testing information, see QUALYS_CONTAINER_SECURITY_INTEGRATION_TESTING.md.

Detected Secret Types

The plugin detects secret categories based on Qualys Container Security rules, including but not limited to:

  • AWS Credentials - AWS Access Keys, Secret Access Keys
  • Private Keys - RSA, EC, DSA private keys; PEM-encoded keys
  • TLS Certificates - X.509 certificates, self-signed certificates
  • API Keys - Google Cloud API keys, GitHub tokens, generic API keys
  • Database Credentials - Database connection strings with embedded credentials
  • OAuth Tokens - OAuth bearer tokens, refresh tokens
  • Generic Credentials - Username/password combinations in config files
  • Certificates in Bundles - Multiple certificates or keys within a single file

Detection is based on Qualys Container Security pattern matching rules which you can configure and extend within Qualys console. Custom rules can be configured in the Qualys UI; underlying rule definitions are regex-based rule entries in the custom-rules workflow.

Limitations

  • Plugin queries Qualys Container Security API, which must have already scanned the container images
  • Container images must be accessible to Qualys (either in a registry or on a scanned host)
  • Scan speed depends on Qualys API responsiveness and number of images in Container Security module
  • Cannot detect secrets outside enabled Qualys Container Security rules (coverage can be extended with custom rules in the Qualys UI)
  • Secrets stored as environment variables (both ENV in Dockerfile and runtime -e / --env-file) are not detected; only secrets embedded in image filesystem files are scanned
  • Secret detection is supported on registry and CI/CD sensors only (Linux, Docker/Containerd/CRI-O); the general/host sensor does not support secret detection
  • Note: If you encounter multi-arch image rejection in registry-sensor mode, consider trying single-arch builds (e.g., --platform linux/amd64) without provenance or SBOM attestations as a potential workaround

References