Code Scanning and Pushed Results¶
Cloud Security can analyze source code in two ways:
- Hosted scanning checks repositories selected by your source-control connection and code-scanning policy.
- Pushed results let a developer or CI pipeline scan a checkout locally, or upload an existing SARIF or CycloneDX document.
Both paths write to the same findings worklist. Use pushed results when source code must stay in your environment, when you already run another scanner, or when you want scan feedback on every push instead of waiting for a scheduled hosted scan.
CLI version
The cloudsec code commands used on this page were added after CLI 5.6.2.
They require the first limacharlie release newer than 5.6.2. Check your
installation before using the examples:
Before you begin¶
You need:
- a LimaCharlie organization subscribed to
ext-cloud-security; - an enabled code-scanning policy that selects the repository;
- an API key with
cloudsec.getandcloudsec.set; - the current LimaCharlie CLI; and
- Docker for local scans. Uploading an existing document does not require Docker.
Authenticate interactively with limacharlie auth login, or set LC_OID and
LC_API_KEY in CI. Create and scope organization API keys as described in
API Keys.
To configure the required policy in the console, open Cloud Security →
Policies → Code scanning, turn on Enable code scanning, and add the
repository's <owner>/<repository> name under Include. Select at least one
hosted scanning engine, then save the policy. The policy can select a repository
even when it does not come from a connected source-control organization.
Repository names use the <owner>/<repository> form, for example acme/api.
If a checkout has a hosted Git remote, the local scan command can infer this
name and the current commit. Pass --repo and --commit explicitly when the
remote does not identify them unambiguously.
Scan a local checkout¶
From the repository root, scan and send the result to Cloud Security:
limacharlie --output yaml cloudsec code scan . \
--repo acme/api \
--commit "$(git rev-parse HEAD)" \
--ingest
The default scan covers software dependencies, infrastructure as code, and licenses. To select supported scanners explicitly, pass a comma-separated list:
limacharlie --output yaml cloudsec code scan . \
--repo acme/api \
--scanners sca,iac,sast,licenses,images \
--ingest
The CLI runs the published LimaCharlie scanner container. The checkout is
mounted read-only. Nothing from the checkout is sent to LimaCharlie unless you
add --ingest; in that case, only the generated report is uploaded.
To inspect or archive a report without uploading it, write it to a file:
The output is a gzipped LimaCharlie report/v1 document. A scan must use either
--ingest, -o, or both, so a completed scan never discards its only copy of
the report.
Secret scanning uses the hosted lane
Local scans do not accept the secrets or secrets_history scanners.
Secret findings require identity data held by the hosted service to merge
safely. Use hosted scanning for credentials and secret history.
Push an existing scanner result¶
Use code ingest when another tool already produced the result. The command
accepts:
sariffor a SARIF results document;cyclonedxfor a CycloneDX bill of materials; orreportfor a LimaCharliereport/v1document produced bycode scan.
For example, push a SARIF file from the current commit:
limacharlie --output yaml cloudsec code ingest \
--repo acme/api \
--source sarif \
--file trivy.sarif \
--commit "$(git rev-parse HEAD)" \
--ref "$(git branch --show-current)"
Or push an existing CycloneDX SBOM:
limacharlie --output yaml cloudsec code ingest \
--repo acme/api \
--source cyclonedx \
--file sbom.cdx.json \
--commit "$(git rev-parse HEAD)"
Files ending in .gz stay compressed in transit. A document can be up to 20
MiB; narrow the scan or split it into separate documents if it exceeds that
limit.
A pushed repository does not need to come from a connected source-control
organization. The push creates the repository entry with only the facts the
document supplies. In that case, also pass --default-branch because no
provider connection can supply it:
limacharlie --output yaml cloudsec code ingest \
--repo acme/private-api \
--source sarif \
--file results.sarif \
--default-branch main \
--commit "$COMMIT_SHA"
The repository must still match an enabled code-scanning policy and counts toward the same repository quota as a connected repository.
Run on every GitHub push¶
Store the organization UUID as the LC_OID Actions secret and a least-privilege
organization API key as LC_API_KEY. Then add
.github/workflows/limacharlie-code-scan.yml to the repository:
name: LimaCharlie code scan
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install LimaCharlie CLI
run: pip install --upgrade limacharlie
- name: Scan and push results
env:
LC_API_KEY: ${{ secrets.LC_API_KEY }}
LC_OID: ${{ secrets.LC_OID }}
run: |
limacharlie --output yaml cloudsec code scan . \
--repo "$GITHUB_REPOSITORY" \
--commit "$GITHUB_SHA" \
--ref "$GITHUB_REF" \
--ingest
The workflow grants GitHub only read access to repository contents. The LimaCharlie key controls the upload and should contain only the permissions listed in Before you begin.
If your existing scanner produces SARIF, replace the final step with that
scanner followed by cloudsec code ingest. For example:
- name: Push SARIF results
env:
LC_API_KEY: ${{ secrets.LC_API_KEY }}
LC_OID: ${{ secrets.LC_OID }}
run: |
limacharlie --output yaml cloudsec code ingest \
--repo "$GITHUB_REPOSITORY" \
--source sarif \
--file results.sarif \
--commit "$GITHUB_SHA" \
--ref "$GITHUB_REF"
Review the result¶
Confirm that Cloud Security recorded the repository:
Then list its open pushed findings:
Repository rows identify their source as ingest, hosted, or both.
Pushed findings use the same triage, ownership, Cases, Outputs, and automation
as hosted findings.
Pushing the same document again is idempotent. When a newer document omits a
finding previously reported by that pushed source, Cloud Security closes that
finding. A pushed document never closes a finding owned by the hosted scanner.
The ingest response also contains notes for results it could not safely
import; for example, credential findings from third-party documents are
deliberately skipped.
Troubleshooting¶
| Problem | What to check |
|---|---|
A cloudsec code command is missing |
Upgrade to a CLI release newer than 5.6.2. |
| The CLI cannot identify the repository | Pass --repo <owner>/<repository> explicitly. |
| Docker is not found | Install and start Docker, or upload a document produced by an existing scanner with code ingest. |
| The repository is not recorded | Confirm that the repository matches an enabled code-scanning policy and is within the organization's repository quota. |
| The document is rejected as too large | Keep it below 20 MiB by narrowing the scan or splitting independent results into separate documents. |
| Secret results do not appear | Use hosted secret scanning; local and third-party secret findings are intentionally not ingested. |