Skip to main content

Pillars analysis jobs and configuration

ReferencePublicInterface: GitLab CI/CD

Pillars selects common source-analysis jobs unless their switches disable them. Most image-analysis jobs additionally require the file at DOCKERFILE_PATH. Set the listed switch to "false" to disable a job. Enabling a job does not provision a scanner service, create an account, or provide the application's test configuration.

Each tool's command determines what counts as a finding or an execution error. The job context rules then determine whether a failed job blocks the pipeline. Reports, skipped jobs, and allowed failures all need review when assessing a build.

Source analysis​

JobDisable switchInputs, output, and failure condition
megalinter-allMEGALINTERUses .mega-linter.yml. When absent, creates a default disabling SPELL_LYCHEE, HTML_DJLINT, REPOSITORY_KINGFISHER, and REPOSITORY_OSV_SCANNER. Retains config and reports under ${EVIDENCE_DIR}/megalinter-reports; enabled linters determine findings. Retries once.
semgrepSEMGREPUses the image's semgrep-SEMGREP_RULESET-ruleset.yml, with SEMGREP_RULESET: ci. Runs with --error and writes JSON, JUnit, SARIF, GitLab SAST, secret-detection, and text outputs. The named ruleset must exist in the image.
trufflehogTRUFFLEHOGScans Git history from the merge-request target branch, or SINCE_BRANCH, default ${CI_DEFAULT_BRANCH}. Supports .trufflehogignore and .trufflehog.yaml. Uses --fail; writes findings and logs as JSON.
dependency-checkDEPENDENCY_CHECKScans the checkout with experimental analyzers enabled, excluding Yarn audit and NodeJS analysis and skipping dev dependencies for the named Node analyzers. Uses --failOnCVSS 7; writes all supported report formats. Retries once.
dockerfile-lintDOCKERFILE_LINTRequires the Dockerfile selection path, reads .hadolint.yaml when present, and fails at Hadolint's error threshold. Writes text, SARIF, JSON, Checkstyle, Code Climate, and SonarQube outputs.
malcontentMALCONTENTScans the checkout, including data files. MALCONTENT_THRESHOLD: "3" fails on a risk score at or above 3; the scale is low 1, medium 2, high 3, critical 4. Writes JSON, Markdown, YAML, terminal output, and logs.
sonarqubeSONARQUBERequires a SonarQube project, token, and properties file. Waits for the configured server quality gate. Retains scanner logs, metadata, and available server evidence.
commitlintCOMMITLINTCreates a Conventional Commits configuration when commitlint.config.js is absent. Validates the merge-request title after removing the Draft: prefix. Also validates commits; the individual-commit check is nonblocking when squash-on-merge is enabled. Outside a merge request, checks commits since the merge base with the default branch.

Configure SonarQube​

Create or identify your application's SonarQube project and obtain a token permitted to analyze it. Store the token as SONAR_TOKEN. SONARQUBE_TOKEN is a compatibility fallback when SONAR_TOKEN is empty. Set SONARQUBE_HOST to your installation's URL; the declared default is https://sonarqube.${PLATFORM_DOMAIN}.

Add a root sonar-project.properties. Replace the sample project key and source directory:

sonar.projectKey=example-service
sonar.projectName=Example service
sonar.sources=src
sonar.sourceEncoding=UTF-8

Do not put the token in that file. The job passes SONAR_PROJECT_PATH, default sonar-project.properties, to the scanner, but its prerequisite check still requires the root file. Keep the default path unless your installation corrects that mismatch.

The job requires dependency-check; disabling it without changing the SonarQube job leaves a required dependency missing. Other listed framework build/test dependencies are optional. Recognized evidence includes npm LCOV, Gradle JaCoCo, Python coverage XML, Go coverage, and .NET OpenCover output at the shared jobs' standard locations. Changing those paths can require matching SonarQube configuration. The server's quality-gate policy determines its thresholds; Pillars does not define one universal SonarQube threshold for every project.

Configure Dependency-Check​

SettingDefaultUse
NVD_API_KEYUnsetCredential for the connected NVD update. A failed update is logged but does not by itself stop the scan.
OSS_INDEX_USERNAME, OSS_INDEX_PASSWORDUnsetOptional OSS Index credentials; both must be populated to add the authenticated arguments.
SUPPRESSIONS_FILEdependency-check-suppressions.xmlOptional suppression file; copied into evidence when present.
DEPENDENCY_CHECK_EXTRA_ARGSEmptyAdditional scanner arguments after the fixed arguments. Use reviewed suppressions and thresholds; do not assume they affect another tool.

The scan uses the locally available database after the update attempt. A report can therefore reflect older data when updating fails. Retain the log with the report.

Configure MegaLinter and commit checks​

Keep .mega-linter.yml and commitlint.config.js in the application project when customizing these checks. Pillars configures JSON, Markdown-summary, and SARIF reporting for MegaLinter and disables its configuration reporter. Environment settings can take precedence over the file. Full declared reporting defaults are in the variable catalog.

The commitlint setup checks specifically for commitlint.config.js before creating its default. A differently named config file can coexist with a newly created default; use that filename for predictable behavior.

Image and application analysis​

These jobs inspect the registry image built by container-image. Its image.env artifact supplies the resolved image coordinates to downstream jobs. They do not wait for a separate container-publication gate because the image is already pushed.

JobDisable switchBehavior and output
grypeGRYPEScans the image directly with GRYPE_FAIL_ON_SEVERITY: high, default search scope all-layers. Produces JSON, CycloneDX XML/JSON, SARIF, and tables. Supports .grype.yaml or .grype/config.yaml.
neuvectorNEUVECTORRequests a repository scan from the NeuVector API and applies the count and score thresholds below. Produces a JSON report and text summary.
syftSYFTInventories the image and checkout separately. Produces Syft text, SPDX JSON, and CycloneDX XML/JSON. It has no vulnerability threshold; execution can still fail.
trivyTRIVYScans image vulnerabilities and secrets. Writes JSON, text, SARIF, CycloneDX, and SPDX outputs. The job sets no explicit nonzero findings exit code; do not treat its report as a guaranteed blocking vulnerability gate. Supports trivy.yaml.
clamscanCLAMSCANInvokes the installed ClamAV wrapper against the image. Retains clamscan-report.txt for 30 days. The wrapper's exit result is subject to the normal job context rules.
oscapOSCAPInvokes the installed OpenSCAP wrapper. Its matching Dockerfile rules allow failure; review results even when the overall pipeline succeeds.
craneCRANEReads image configuration and requires a numeric USER, optionally uid:gid. An absent or named user fails. Numeric 0 matches the current check; this does not establish a non-root runtime.
zapZAPStarts the built image as a service, runs a baseline web scan, and normally a full scan. Requires container-image and crane. Retains HTML, Markdown, XML, JSON, SARIF, and logs.
cypressCYPRESSStarts the built image as a service and runs the project's Cypress tests. Requires container-image, crane, and cypress.config.js or cypress.config.ts. Retains JUnit, logs, downloads, screenshots, and videos.

A GitLab report declaration does not guarantee that every GitLab edition or report schema renders a security dashboard. Job artifacts are the direct record to inspect. Pillars does not convert every scanner report into the native GitLab security schema.

Configure NeuVector​

The runner must reach the controller, and the controller must be able to pull the image. Store NV_X_AUTH_APIKEY as a secret CI/CD variable.

SettingDefault
NV_API_HOSTneuvector-svc-controller.neuvector.svc.cluster.local
NV_API_PORT10443
NV_API_SCAN_URLhttps://$NV_API_HOST:$NV_API_PORT/v1/scan/repository
NV_REGISTRY_URL, NV_REGISTRY_USER, NV_REGISTRY_PASSWORDhttps://${REGISTRY}, ${REGISTRY_USER}, ${REGISTRY_PASSWORD}
NV_REPOSITORY, NV_TAG${IMAGE}, ${IMAGE_TAG}
THRESHOLD_HIGH, THRESHOLD_MEDIUM, THRESHOLD_LOW0, 5, 99
THRESHOLD_SCORE_V37.0
REPORT_FILE, SUMMARY_FILE${EVIDENCE_DIR}/scan-repository.json, ${EVIDENCE_DIR}/scan-summary.txt

The job fails when the number of High, Medium, or Low findings exceeds the corresponding limit, or any finding's score_v3 exceeds 7.0. These are distinct conditions. The current request uses curl -k; this job's success does not prove that the controller's TLS certificate was validated. Scanning repeats while the report is empty and remains subject to the GitLab job timeout.

Configure application tests​

APP_HTTP_PORT defaults to 8080. ZAP's ZAP_TARGET and Cypress's CYPRESS_BASE_URL default to http://${CI_PROJECT_NAME}:${APP_HTTP_PORT}. The service must start from the built image with its normal entrypoint and expose the application at that address. Supply required application configuration through the project's service-compatible variables. Neither job provisions a database or adds a universal application readiness check.

ZAP optionally consumes zap.conf, zap-progress.json, and zap.context. ZAP_FULL_SCAN_DISABLED: "true" skips the full scan; baseline remains enabled. The scripts use -I, and the full-scan path contains an explicit success exit. Treat ZAP outputs as scan evidence, not a universally enforced findings gate. Use only an authorized test target, especially when overriding the default URL for the full scan.

Cypress fails early if neither config file exists. When both exist, the setup records the TypeScript filename last; avoid duplicate configurations. The configured test runner must be able to reach the service and execute its tests.

For a container that does not provide an HTTP application, disable those two jobs:

variables:
ZAP: "false"
CYPRESS: "false"

If you also disable CRANE, keep ZAP and Cypress disabled or deliberately replace their required dependencies. The jobs otherwise refer to a missing prerequisite.

Disconnected scanning​

With AIRGAP_MODE: "true":

  • Grype disables automatic database updates and database-age validation. The common image job also sets GRYPE_DB_MAX_ALLOWED_BUILT_AGE to 120h, but validation is off.
  • Trivy sets TRIVY_OFFLINE_SCAN, TRIVY_SKIP_CHECK_UPDATE, TRIVY_SKIP_DB_UPDATE, and TRIVY_SKIP_JAVA_DB_UPDATE to "true".
  • ClamAV's wrapper receives OFFLINE: "true".
  • Dependency-Check skips its update attempt and adds --disableOssIndex.
  • npm audit is omitted.

These switches require prepopulated scanner data and reachable internal services. They do not make all other tools offline-capable. Record scanner versions and database freshness when interpreting the evidence. Installed image defaults, including the wrapper behavior for ClamAV and OpenSCAP, must match your platform's supported toolchain.

Locate results​

Open the relevant job in your project's pipeline and download or browse its artifacts. The default evidence root is JOB_NAME_SLUG/evidence; SBOMs use JOB_NAME_SLUG/sbom. For example, inspect grype/evidence/grype-output.txt and syft/sbom/syft-image-sbom.cyclonedx.json. An application test's logs are separate from the scanner findings.

If a credential was detected, revoke or rotate it using your incident process; deleting the string from a later commit does not invalidate it. For other findings, retain the report and image reference, review the affected package or code, fix or approve an exception through the responsible team, and run a new pipeline.