Skip to content

feat: add vulnerability CLI commands for ext-vulnerability-reporting#288

Merged
maximelb merged 3 commits into
cli-v2from
cli-v2-vulnerability
May 4, 2026
Merged

feat: add vulnerability CLI commands for ext-vulnerability-reporting#288
maximelb merged 3 commits into
cli-v2from
cli-v2-vulnerability

Conversation

@maximelb
Copy link
Copy Markdown
Contributor

@maximelb maximelb commented May 4, 2026

Summary

Adds a dedicated limacharlie vulnerability command set that wraps the
ext-vulnerability-reporting
extension's RPC actions behind typed SDK and Click surfaces.

The extension keeps a per-org index of OS packages reported by sensors and
joins it against a CVE database; this PR exposes the public actions of that
index as first-class CLI commands instead of forcing users through
limacharlie extension request.

CLI surface

  • vulnerability scan --sid <SID> — trigger an on-demand os_packages scan
  • vulnerability dashboard [--sort-asc] — per-org dashboard graphs
  • vulnerability cve list — CVEs observed across the org
  • vulnerability cve get <CVE-ID> — raw NVD record
  • vulnerability cve hosts <CVE-ID> — hosts affected by a CVE
  • vulnerability cve packages <CVE-ID>(name, version) pairs affected by a CVE
  • vulnerability host list — endpoints with vulnerability counts
  • vulnerability host packages <SID> — vulnerable packages on one host

The list-style commands share a common option block (--cursor, --limit,
--sort-by, --sort-asc, --filter KEY=VALUE repeats, --filters-json
escape hatch, --search-field/--search-op/--search-value, --include-tags)
mirroring the extension's VulnQueryRequest schema.

Subscription management stays under limacharlie extension; this group is
purely the user-facing query / scan-trigger surface.

Envelope unwrap

Adds an opt-in unwrap flag to Extensions.request(...). The extension
framework returns {data, error, retry}; with unwrap=True the SDK returns
just the inner data. The new Vulnerability SDK passes unwrap=True
everywhere so the CLI surfaces clean payloads — JMESPath filters can address
fields directly (results[*].cve instead of data.results[*].cve) and
--output table renders rows instead of {N keys}. Default stays False
to keep feedback, cases, configs, and extension request byte-compatible.

Example output (against lc_demo)

$ limacharlie vulnerability dashboard
{
  "values": [
    {
      "graph": "platform_string",
      "values": [{"count": 3, "platform_string": "windows"}]
    },
    {
      "graph": "severity",
      "values": [{"count": 3, "severity": "high"}]
    }
  ]
}
$ limacharlie vulnerability cve list --limit 5
{
  "next_cursor": "",
  "results": [
    {"count": 3, "cve": "CVE-2017-0037", "severity": "high"}
  ],
  "total_return_count": 1
}
$ limacharlie vulnerability cve hosts CVE-2017-0037
{
  "cursor": "",
  "hosts": [
    {"hostname": "5_3_1.c.lc-developers.internal.", "platform_string": "windows", "sid": "0b1e0588-..."},
    {"hostname": "5_3_0.c.lc-developers.internal.", "platform_string": "windows", "sid": "b2a0e3d1-..."},
    {"hostname": "5_2_0.c.lc-developers.internal.", "platform_string": "windows", "sid": "22551288-..."}
  ],
  "total": 3
}
$ limacharlie vulnerability cve packages CVE-2017-0037
{
  "cursor": "",
  "packages": [
    {"count": 2, "package_name": "Microsoft Edge", "package_version": "147.0.3912.86"},
    {"count": 1, "package_name": "Microsoft Edge", "package_version": "147.0.3912.98"}
  ],
  "total": 2
}
$ limacharlie vulnerability host packages 0b1e0588-7e58-4b05-bba8-a356b3938c38
{
  "cursor": "",
  "packages": [
    {
      "count": 1,
      "cve": "CVE-2017-0037",
      "package_name": "Microsoft Edge",
      "package_name_package_version_cve": "Microsoft Edge_147.0.3912.98_CVE-2017-0037",
      "score": 8.1,
      "severity": "high"
    }
  ],
  "total": 1
}
$ limacharlie vulnerability scan --sid 0b1e0588-7e58-4b05-bba8-a356b3938c38
{
  "message": "Package scan initiated successfully",
  "sid": "0b1e0588-7e58-4b05-bba8-a356b3938c38"
}
$ limacharlie vulnerability cve list --output table
Field               Value
------------------  --------------------------------------------------------
next_cursor
results             {'count': 3, 'cve': 'CVE-2017-0037', 'severity': 'high'}
total_return_count  1
$ limacharlie --filter 'results[*].cve' vulnerability cve list
[
  "CVE-2017-0037"
]

Files

  • limacharlie/sdk/extensions.py — add unwrap flag to request()
  • limacharlie/sdk/vulnerability.pyVulnerability SDK class wrapping the eight RPC actions
  • limacharlie/commands/vulnerability.py — Click group + subgroups + register_explain entries
  • limacharlie/cli.py — register vulnerability in _COMMAND_MODULE_MAP
  • tests/unit/test_sdk_extensions.py — 3 envelope/unwrap tests
  • tests/unit/test_sdk_vulnerability.py — 12 SDK tests
  • tests/unit/test_cli_vulnerability.py — 19 CLI tests
  • tests/unit/test_cli_lazy_loading_regression.py — extend snapshots for the new command

Test plan

  • python -m pytest tests/unit -p no:benchmark passes
  • Manual: query commands against lc_demo (dashboard, cve list/get/hosts/packages, host list/packages)
  • Manual: limacharlie vulnerability scan --sid <SID>
  • Manual: filter / sort / search flags
  • Manual: JMESPath --filter works directly on payload (no data. prefix needed)

🤖 Generated with Claude Code

maximelb and others added 2 commits May 4, 2026 09:23
Adds a dedicated `limacharlie vulnerability` command set that wraps
the ext-vulnerability-reporting extension's RPC actions (query_cves,
query_cve, query_cve_vuln_hosts, query_cve_vuln_packages,
query_endpoints, query_host_vuln_packages, query_dashboard,
scan_packages) behind typed SDK and Click surfaces.

Subscription management stays under `limacharlie extension`; this
group is purely the user-facing query / scan-trigger surface.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds an opt-in unwrap parameter to limacharlie.sdk.extensions.Extensions.request
that returns the inner data field of the standard {data, error, retry}
extension envelope instead of the whole response. Default stays False to keep
existing callers (feedback, cases, configs, the extension request CLI)
byte-compatible.

The new vulnerability SDK opts in everywhere so its CLI surfaces clean
payloads — JMESPath filters can now address fields directly (e.g.
'results[*].cve' instead of 'data.results[*].cve') and --output table
renders rows instead of '{N keys}'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@maximelb
Copy link
Copy Markdown
Contributor Author

maximelb commented May 4, 2026

/gcbrun

@maximelb maximelb requested a review from dzimine-lc May 4, 2026 18:21
The simulate flag was a debug knob from the extension's testing
pipeline; it doesn't belong in the user-facing CLI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@maximelb maximelb marked this pull request as ready for review May 4, 2026 18:28
@maximelb maximelb merged commit 01d0f48 into cli-v2 May 4, 2026
7 checks passed
@maximelb maximelb deleted the cli-v2-vulnerability branch May 4, 2026 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant