Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/snippet-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
# reorganizes modules fails the PR that bumps it, not an unrelated PR.
run: |
pip install --upgrade pip
pip install 'limacharlie==5.5.1'
pip install 'limacharlie==5.6.2'

- name: Byte-compile (do not run) the Python snippets
run: python -m py_compile snippets/python/*.py
Expand All @@ -83,5 +83,6 @@ jobs:
from limacharlie.sdk.organization import Organization
from limacharlie.sdk.search import Search
from limacharlie.sdk.hive import Hive, HiveRecord
from limacharlie.sdk.cloudsec import CloudSec
print("SDK import paths used by the documentation snippets all resolve.")
PY
43 changes: 42 additions & 1 deletion docs/6-developer-guide/mcp-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,15 @@ The MCP server enforces the same permission model as the LimaCharlie REST API. T

### Permission Enforcement

The API enforces permissions strictly. Any operation attempted without the required permission will fail with a `401` error that specifies the missing privilege. The AI assistant will surface these errors and indicate which permission is needed.
Organization-scoped MCP operations require `ai_agent.operate` by default, in
addition to the API permission for the requested operation. The server or API
reports missing privileges; an authentication failure and a permission denial
are different problems. Read the returned error before changing credentials.

Profiles select the tools offered and callable on an endpoint; they do not grant
permissions. Prefer a product's read-only profile with a read-only key for a first
review. An unknown profile endpoint can return 404. Inspect the tool list because a server-wide
configured profile can override the URL profile.

### Recommended Permissions by Use Case

Expand Down Expand Up @@ -239,6 +247,37 @@ For full platform management (includes all of the above, plus):
| `cloudsensor.get`, `cloudsensor.set`, `cloudsensor.del` | Manage cloud sensor adapters |
| `externaladapter.get`, `externaladapter.set`, `externaladapter.del` | Manage external adapters |

#### CloudSec, CodeSec and MailSec

Start with a small, read-only product review, then grant the particular write
permission only when the workflow needs it:

| Workflow | Profile | Permissions beyond `ai_agent.operate` |
|---|---|---|
| CloudSec posture and CodeSec findings | `cloud_security_readonly` | `cloudsec.get` |
| CloudSec triage and code ingest | `cloud_security` | `cloudsec.get`, `cloudsec.set` |
| Dependency AutoFix and remediation run creation/decision | `cloud_security` | `cloudsec.respond` (separate from `cloudsec.set`) |
| MailSec coverage, messages, campaigns and histories | `email_security_readonly` | `mailsec.get` |
| Raw email download | `email_security` | `mailsec.get` and `mailsec.get.eml` |
| MailSec EML analysis, rule validation/backtest and selected bulk preview | `email_security_readonly` | `mailsec.get` |
| MailSec provider diagnostics, campaign preview, verdict revision or remediation | `email_security` | `mailsec.act` |
| MailSec report resolution/reopening | `email_security` | `mailsec.set` |
| Product provider/policy/secret setup | `platform_admin` | Dedicated provider `.get/set`, product `.get/set` for policy, `secret.set` and required metadata-read access |

CloudSec requires the `ext-cloud-security` subscription; MailSec requires
`ext-email-security` and applicable beta access. Setup uses generic Hive and
extension tools, the console or CLI; product read-only profiles exclude those
writes. MailSec's read-only profile excludes raw EML and privileged diagnostics.
Backend capability rollout remains independent of the client version.

Use `https://mcp.limacharlie.io/mcp/cloud_security_readonly` or
`https://mcp.limacharlie.io/mcp/email_security_readonly` for a supported hosted
profile. With a local server, select the same name using `MCP_PROFILE`.
Follow [CloudSec in your IDE](../cloud-security/mcp.md),
[MailSec with an AI assistant](../email-security/mcp.md), or the
[MCP source onboarding guide](https://github.com/refractionPOINT/lc-mcp-server/blob/master/docs/SECURITY-PRODUCTS.md)
for pilot setup and first tools.

### Assigning Permissions

**For users (OAuth/JWT):**
Expand Down Expand Up @@ -273,6 +312,8 @@ Once connected, AI assistants can:
- **Take response actions** — Isolate endpoints, kill processes, manage tags
- **Search threat intelligence** — Query IOCs and map to MITRE ATT&CK
- **Configure the platform** — Manage outputs, adapters, secrets, and playbooks
- **Review CloudSec and CodeSec** — Inspect posture, repositories, findings and coverage
- **Triage MailSec** — Review coverage, messages, campaigns and action history

---

Expand Down
43 changes: 39 additions & 4 deletions docs/6-developer-guide/sdks/python-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
10. [Hive Operations](#hive-operations)
11. [Search (LCQL)](#search-lcql)
12. [Extensions](#extensions)
13. [Infrastructure as Code](#infrastructure-as-code)
14. [Error Handling](#error-handling)
15. [Complete Examples](#complete-examples)
13. [Cloud, Code and Email Security](#cloud-code-and-email-security)
14. [Infrastructure as Code](#infrastructure-as-code)
15. [Error Handling](#error-handling)
16. [Complete Examples](#complete-examples)

## Overview

Expand All @@ -41,7 +42,7 @@ The LimaCharlie Python SDK provides a comprehensive interface for interacting wi

### Requirements

- Python 3.9 or higher
- Python 3.10 or higher
- pip package manager

### Install via pip
Expand Down Expand Up @@ -710,6 +711,40 @@ response = ext.request(
)
```

## Cloud, Code and Email Security

### Cloud Security

The SDK exposes `CloudSec` through `limacharlie.sdk.cloudsec`. The
organization must be subscribed to Cloud Security; reading findings requires
`cloudsec.get`. This example follows every page while keeping its filters unchanged:

```python
--8<-- "snippets/python/cloudsec_findings.py"
```

The wrapper returns response dictionaries rather than typed finding objects.
Connection and policy configuration uses `Hive` (`cloudsec_provider`,
`cloudsec_policy`, `cloudsec_query`, `cloudsec_code_rule`). See
[Cloud Security setup](../../cloud-security/setup-cli.md) for the permission
split and [API reference](../../cloud-security/api-reference.md) for response
fields.

### Code Security and Email Security availability

Install or upgrade the SDK with `python -m pip install --upgrade limacharlie`.
Use `CloudSec` for Cloud Security and Code Security, and `Mailsec` for Email
Security. Follow [Code Security setup](../../cloud-security/code-security/getting-started.md)
or [Email Security setup](../../email-security/setup-cli.md) to configure the
product subscription, provider connection and permissions.

Email Security requires its extension subscription and separates reading
(`mailsec.get`), policy/triage edits (`mailsec.set`), provider actions
(`mailsec.act`) and raw-email access (`mailsec.get.eml` on top of
`mailsec.get`). Provider records have their own `mailsec_provider` permissions.
See [Email Security API reference](../../email-security/api-reference.md) and
[permission setup](../../email-security/setup-cli.md#2-grant-the-permissions).

## Infrastructure as Code

```python
Expand Down
12 changes: 8 additions & 4 deletions docs/cloud-security/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ Authentication is the standard `Authorization: Bearer <JWT>` header.
!!! info "Permissions & enable gate"
Reads — and the read-only preview `POST`s (`query`, `simulate/resources`,
`simulate/findings`, `policy/suggest`) — require `cloudsec.get`; every
other write requires `cloudsec.set`. Every route requires the
organization to be subscribed to `ext-cloud-security` — a `403` on any
route means subscribe first. The `oid` is always taken from the
other ordinary write requires `cloudsec.set`. Code Security remediation and
AutoFix require `cloudsec.respond`; see [their route permissions](code-security/reference.md#api-routes).
Every route requires the organization to be subscribed to
`ext-cloud-security`. For a `403`, check both the subscription and the
permission named in the error. The `oid` is always taken from the
authorized path. Provider *records* are not `/cloudsec` routes: their
CRUD goes through Hive (`cloudsec_provider` hive, gated by
`cloudsec_provider.get/set/del`).
Expand Down Expand Up @@ -94,7 +96,9 @@ One route sits outside the `{oid}` path — the MSSP cross-tenant board:

## Writes

All writes are `POST` with a JSON body and require `cloudsec.set`.
The writes below use `POST` with a JSON body. Ordinary configuration, triage and
ingest writes require `cloudsec.set`; Code Security AutoFix instead requires
`cloudsec.respond` and creates a governed remediation run.

| Route | Body | Returns |
|---|---|---|
Expand Down
43 changes: 26 additions & 17 deletions docs/cloud-security/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ standard `limacharlie hive` commands — see
[Configuration](configuration.md); this group is the query and triage
surface.

--8<-- "includes/code-security-cli.md"

For Code Security (repositories, SBOMs, AutoFix, local scans and pushed results), see
[Code Security](code-security/results.md#from-the-cli) and
[Bring your own scanner](code-security/bring-your-own-scanner.md).
Expand Down Expand Up @@ -167,7 +169,11 @@ limacharlie cloudsec finding list \
--sort lc_risk --order desc \
--limit 50
# ...then pass the returned next_cursor back:
limacharlie cloudsec finding list --cursor "<next_cursor>" --limit 50
limacharlie cloudsec finding list \
--severity CRITICAL --severity HIGH \
--status open -q payment \
--sort lc_risk --order desc \
--cursor "<next_cursor>" --limit 50
```

Boolean tri-state flags (`--kev/--no-kev`, `--reachable/--no-reachable`)
Expand All @@ -181,16 +187,10 @@ applies to `finding list`, `finding facets`, `finding causes`, and
that defaults to **ascending** (soonest deadline first), keeping findings with
no due date last rather than dropping them.

!!! note "`--sla` needs a CLI newer than 5.6.1"
The SLA selector and the `due_at` sort key ship in the first `limacharlie`
release after 5.6.1. On an older CLI, use the `sla=` and `sort=due_at`
parameters on the [REST route](api-reference.md#reads) — the server-side
feature is live either way.

The other lists carry a subset, so check `--help` before assuming a flag is
there. `caasm coverage` behaves like `finding list` (repeatable filters,
`--sort`/`--order`, paging). `inventory list` and `caasm assets` page but do
not sort, and inventory's `--type` / `--provider` / `--account` / `--region`
`--sort`/`--order`, paging). `caasm assets` supports paging and `--sort urn` or `--sort last_seen`.
`inventory list` pages without sorting, and inventory's `--type` / `--provider` / `--account` / `--region`
each take a single value rather than repeating. `attack-path list` returns
the headline set in one shot: repeatable filters and `-q`, but no sorting and
no paging.
Expand All @@ -215,19 +215,28 @@ the returned sample, and `simulate resources` takes a repeatable
`--resource-type` to narrow the walked types the way an exclusions rule does.
`policy suggest` takes `--limit` (default 20, cap 50).

## Additional selectors

These selectors are available in the CLI. Check each command's `--help` for
usage; the corresponding REST selectors are in the [API reference](api-reference.md).

| Command | Additional selectors |
|---|---|
| `cloudsec image list` | Repeatable `--lineage-status` (`verified`, `asserted`, `inferred`, `ambiguous`, `unknown`). Stale lineage counts as unknown. |
| `cloudsec image repo-facets` | `--lineage-facet` adds digest-level lineage counts; these counts are separate from registry placement counts. |
| `cloudsec caasm assets` | Repeatable `--kind`, `--source`, `--encryption`, `--screen-lock`, `--compromised`, `--managed`, plus `--sort urn` or `--sort last_seen`. For a posture dimension, an empty value selects unreported state. |
| `cloudsec export findings`, `cloudsec export inventory` | `--max-rows` bounds a CSV chunk; `--cursor` resumes it. A trailing `# next_cursor=...` comment carries the continuation token when more rows remain. Keep all selectors unchanged when resuming. |
| `cloudsec provider m365-certificate` | Generates and stores an Entra connection key pair and returns only its public certificate. See [certificate setup](provider-setup/entra.md#without-the-web-app). |

A CSV reader should skip `#` comment lines before treating the file as a table.
Check for the continuation token before considering a bounded export complete.

## Scripting

The SDK class behind the CLI is available directly:

```python
from limacharlie.client import Client
from limacharlie.sdk.organization import Organization
from limacharlie.sdk.cloudsec import CloudSec

cs = CloudSec(Organization(Client(oid="...")))
page = cs.list_findings(severity=["CRITICAL"], kev=True, limit=100)
for f in page["findings"]:
print(f["lc_risk"], f["title"], f["resource_urn"])
--8<-- "snippets/python/cloudsec_findings.py"
```

Each method mirrors one API route and returns the raw response dict; see the
Expand Down
80 changes: 72 additions & 8 deletions docs/cloud-security/code-security/autofix.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ For a vulnerable dependency with a published fixed version, Code Security can
open the GitHub pull request that upgrades it. You review and merge it like any
other pull request.

AutoFix is GitHub-only and supports **npm** (including yarn and pnpm projects),
**pip**, **Go modules** and **Maven**.
The walkthrough below uses GitHub. AutoFix supports **npm** (including yarn and
pnpm projects), **pip**, **Go modules** and **Maven**. GitLab.com and Bitbucket
Cloud workflow support is deployment-dependent: confirm workflow availability
with LimaCharlie, configure the provider's separate write token, then use
`code capabilities` to verify the connection can open fix pull requests. A
connection missing from that workflow response may still support
ordinary scheduled repository scanning.

## Turn it on

Expand Down Expand Up @@ -77,18 +82,21 @@ stale-lockfile warning and the command to run on the branch before merging:
| Lockfile | Command |
|---|---|
| `package-lock.json` | `npm install --package-lock-only --ignore-scripts` |
| `yarn.lock` | `yarn install --mode update-lockfile` |
| `pnpm-lock.yaml` | `pnpm install --lockfile-only` |
| `go.sum` | `go mod tidy` |
| `npm-shrinkwrap.json` | `npm install --package-lock-only --ignore-scripts` |

This warning applies to npm's JSON lockfiles. A yarn, pnpm or Go lockfile the
service cannot complete safely is refused before the job runs, rather than
opened with a stale-lockfile warning.

AutoFix never runs a package manager, because that would run code from the very
dependencies under suspicion. To update `package-lock.json`, it makes one
read-only request to the npm registry for the new version's download URL and
integrity hash, and writes those into the lockfile.

To forbid that registry request, set `autofix_registry_access: false` in the
policy. npm pull requests then change `package.json` only and carry the
stale-lockfile warning. If any policy selecting a repository sets it to `false`,
policy. Projects using npm JSON lockfiles then change `package.json` only and
carry the stale-lockfile warning. Other lockfile formats can instead be refused
if safe completion needs registry metadata. If any policy selecting a repository sets it to `false`,
that wins.

Separately, LimaCharlie always confirms the fixed version exists on the public
Expand All @@ -97,7 +105,8 @@ request. Packages published only to a private registry cannot be fixed
automatically.

AutoFix also refuses changes it cannot make safely, and says why: transitive
dependencies, Go upgrades across a major version, complex npm version ranges,
dependencies, Go upgrades that require a module-path change for major versions
above v1 (v0-to-v1 is allowed), complex npm version ranges,
Maven versions inherited from a parent POM, and pip pins other than `==`, `===`,
`~=` or `>=`.

Expand Down Expand Up @@ -138,3 +147,58 @@ Some requests are refused immediately, with an HTTP error:

See [Unknown, partial and refusal reasons](reasons.md#remediation-runs) for
every code.

## AI-proposed fixes

!!! warning "Not currently available"
AI-proposed fix pull requests are a separate capability from dependency
AutoFix. They are not currently enabled as an available service. The
configuration below describes the opt-in contract for organizations that
LimaCharlie enables in a future preview; saving it does not grant access.

The `ai_fix_pr` action proposes a change to the single file named by a hosted
static-analysis or infrastructure-as-code finding. It uses **your Anthropic
API key**, sends that file and the finding context to Anthropic, and charges
usage to your Anthropic account. Review [AI data handling](data-handling.md#ai)
before opting in. Dependency upgrades continue to use deterministic AutoFix.

When this capability is available, it needs the GitHub write grants above,
`cloudsec.respond` for requesting and approving each run, and an `ai_fix` block
on an enabled code-scanning policy that selects the repository:

```yaml
# Add this block INSIDE the code_scanning object in your existing policy.
ai_fix:
enabled: true
model_secret: hive://secret/code-fix-anthropic-key
job_cap_usd: 2
jobs_per_day: 10
checks: [syntax]
```

Create the referenced enabled secret first, with your Anthropic API key as the
secret value. The optional `model` selects a supported model; omit it to use the
service default and confirm the available models with LimaCharlie during setup.

| Field | Contract |
|---|---|
| `enabled` | Required inside the block. `false` denies AI fixes for every repository the policy selects. Absent `ai_fix` leaves AI fixes off unless another selecting policy enables them. |
| `model_secret` | Required when enabled; a `hive://secret/<name>` reference, never an inline API key. |
| `job_cap_usd` | Per-model-call budget, USD 0.10–10; default 2. A job that cannot fit its input and output budget makes no model call. |
| `jobs_per_day` | Per-organization daily job cap, 1–50; default 10. Failed jobs count when they start. |
| `checks` | `syntax` (default) or `none`. The service never accepts a command to execute. `none` skips only the optional syntax check; rescanning and the impact gate remain mandatory. |

Across selecting policies, an explicit denial wins, caps take the lowest value,
and required checks combine. Conflicting model or secret choices refuse the
job. The default syntax check supports Go, JSON, YAML, Terraform and HCL files;
unsupported file types are refused rather than treated as having passed.

The model cannot choose a repository, target file, branch, commit or command.
A proposed patch must remove the target finding in a sandboxed rescan, pass the
configured checks, and pass the live-impact gate before a pull request opens.
Missing or partial evidence refuses the job. Each run still needs explicit
approval, and its pull request needs your normal review and merge process.

To disable this opt-in, set `ai_fix.enabled: false` in a policy selecting the
repository. Cancel any active run separately; changing a policy does not close
pull requests already opened.
Loading
Loading