From securin-platform
Use this skill when the user asks to "find exposures where...", "show open critical exposures", "how many exposures...", "break down exposures by severity/status/SLA", "list exposures in my environment matching...", "exposure distribution", "exposures over time", or any ad-hoc exposure search / filter / aggregation. Use this for exposure records specifically (instances found in the user's environment); for global CVE intelligence use securin-cve-enrichment. Requires the Securin Platform MCP server.
How this skill is triggered — by the user, by Claude, or both
Slash command
/securin-platform:securin-exposure-triageThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Ad-hoc search, filtering, and aggregation of the user's **exposures** — instances of vulnerabilities, misconfigurations, or findings discovered in their environment. Translate questions like "show me all open critical exposures breaching SLA" into the correct `search*Data` / `aggregate*Data` call with proper scoping and deep links.
references/_shared/account-preflight.mdreferences/_shared/brand.mdreferences/_shared/composite-fields.mdreferences/_shared/composite-vs-source.mdreferences/_shared/deep-links.mdreferences/_shared/fql-grammar.mdreferences/_shared/groupby-allowlist.mdreferences/_shared/securin_logos/README.mdreferences/_shared/securin_logos/Securin_logo_purple.pngreferences/_shared/securin_logos/Securin_logo_purple.svgreferences/_shared/securin_logos/Securin_logo_rounded.pngreferences/_shared/securin_logos/Securin_logo_rounded.svgreferences/_shared/securin_logos/Securin_logo_white.pngreferences/_shared/securin_logos/Securin_logo_white.svgreferences/_shared/sorting-rules.mdreferences/_shared/source-fields.mdreferences/exposure-fields.mdAd-hoc search, filtering, and aggregation of the user's exposures — instances of vulnerabilities, misconfigurations, or findings discovered in their environment. Translate questions like "show me all open critical exposures breaching SLA" into the correct search*Data / aggregate*Data call with proper scoping and deep links.
An exposure is an instance (e.g., "CVE-2024-3400 on host web-01"). A vulnerability is the global CVE record. This skill is about exposures; use securin-cve-enrichment for vulnerability intel.
See _shared/account-preflight.md. Resolve account-id(s) and validate access before any query. If the question implies a workspace subset, resolve workspace-ids too.
Before using this skill, read every file in the references folder, including the shared references/_shared/ docs.
Exposures are affected by the composite flag too — composite accounts have a separate composite-exposure index with compositeExposure.* field paths and use the exposureQuery tool (source accounts use searchExposureData + aggregateExposureData). See _shared/composite-vs-source.md. Cache the flag for the turn — picking the wrong model returns empty results with no error.
searchExposureData — flat listaggregateExposureData — bucketed count (TERMS) and time-bucketed histogram (DATE_HISTOGRAM)aggregateVulnerabilityTimelineData / searchVulnerabilityTimelineData — historical vulnerability state changes over time (if available for account; fall back to DATE_HISTOGRAM if 404)getApiFields with entityType: ["EXPOSURE"] — field discoverygetGroupByFields — valid aggregation dimensionsgetTopValues — enum values for a fieldgetDefaultViewForGroupByField — platform's default column set for a groupingvalidateFilter — FQL construction + validationgetEffectiveAccessWorkspaces — workspace scopingcreateDeepLink (preferred) — call once per list/aggregation, plus once per bucket if you need per-bucket linksgetDeepLink — URL for a known exposure-id| Shape | Example | Tool |
|---|---|---|
| Flat list | "List open critical exposures" | searchExposureData |
| Single-field bucket | "Exposures by severity" | aggregateExposureData |
| Time series | "Exposures created per week over 6 months" | aggregateVulnerabilityTimelineData or aggregateExposureData DATE_HISTOGRAM |
| Aggregation with per-bucket deep links | "Bucket counts, clickable" | aggregateExposureData + one createDeepLink per bucket |
getApiFields(entityType=["EXPOSURE"])
getTopValues(field="exposure.status")
getGroupByFields(entityType="EXPOSURE")
See _shared/fql-grammar.md. Exposure-specific patterns:
exposure.status = 'Open'
exposure.scores.scoreLevel = 'Critical'
"exposure.scores.score" >= 7.0 # numeric — sort uses the same path: exposure.scores.score:desc
"exposure.firstDiscoveredOn" >= "2026-01-01T00:00:00Z"
exposure.remediationTarget.status = 'Overdue'
exposure.assignments.assignedTo.name = 'team:remediation'
exposure.mappedAttributes.vulnerabilityIds = 'CVE-2024-3400'
exposure.mappedAttributes.type like 'Vulnerability'
Cross-entity filters (exposure → vuln / asset):
# Exposures tied to a specific CVE — correct cross-entity field is vulnerabilities.id
vulnerabilities.id = 'CVE-2024-3400'
# ❌ vulnerabilities.vulnerabilityId → 400 Invalid field
# ❌ vulnerabilities.cveId → 400 Invalid field
# Exposures tied to exploited vulnerabilities
vulnerabilities.isCisaKEV = true
# Exposures on exposed-to-internet assets (source-model account)
asset.reachability = 'Exposed'
# Same, composite-model account
compositeAsset.reachability = 'Exposed'
aggregateVulnerabilityTimelineData / searchVulnerabilityTimelineData first. If those return 404, fall back to aggregateExposureData with DATE_HISTOGRAM.aggregateExposureData to get the buckets, then call createDeepLink once per bucket with the bucket's filter narrowed by the bucket value.aggregateExposureData — correct request shapefunction is an object with a type discriminator. Type-specific parameters (field, size, etc.) go inside the function object:
{
"filters": "exposure.status = 'Open'",
"aggs": [{
"name": "bySeverity",
"function": {"type": "TERMS", "field": "exposure.scores.scoreLevel", "size": 10}
}]
}
Common mistakes that cause 400/500:
"function": "TERMS" — function must be an object, not a string"apiPath": "..." — key must be "field", not "apiPath""field": "exposure.workspaceId" — returns 500; use "asset.workspaces.name" for workspace groupingaggregateExposureData with DATE_HISTOGRAM — time series shapeDifferent structure from TERMS: nested aggs use "aggs", and interval must be Title Case. isFixedInterval, extendedBounds, and hardBounds are required:
{
"aggs": [{
"name": "openedByMonth",
"function": {
"type": "DATE_HISTOGRAM",
"field": "exposure.firstDiscoveredOn",
"interval": "Month",
"isFixedInterval": false,
"extendedBounds": {"min": "2025-11-01T00:00:00Z", "max": "now"},
"hardBounds": {"min": "2025-11-01T00:00:00Z"}
},
"aggs": [{"name": "count", "function": {"type": "COUNT", "field": "exposure.exposureId"}}]
}]
}
Valid interval values (Title Case only): "Day", "Week", "Month", "Quarter", "Year".
❌ "month", "MONTH", "1M", "MONTHLY" all return 400.
Every result table adds a View in Platform column. Every bucket in an aggregation gets its own URL. Call createDeepLink once per reported scope; getDeepLink(exposureId) for individual drill-downs.
**Query:** <plain-English restatement>
**Account:** <account name + id>
**Filter:** `<FQL>`
<results table with View-in-Platform links>
[View full list in Platform](<top-level deep link>)
**Observations:**
- <Pattern noted — e.g., "70% of critical exposures are in one workspace">
- <Suggested next step — e.g., "Drill into remediation: use securin-remediation-guidance for the top 3">
searchExposureData
filter: exposure.status = 'Open'
AND exposure.scores.scoreLevel = 'Critical'
AND exposure.remediationTarget.status = 'Overdue'
sort: "exposure.scores.score:desc"
Run aggregateExposureData once per dimension (two calls):
// Call 1 — by severity
{
"filters": "exposure.status = 'Open'",
"aggs": [{"name": "bySeverity", "function": {"type": "TERMS", "field": "exposure.scores.scoreLevel", "size": 10}}]
}
// Call 2 — by workspace (use asset.workspaces.name — exposure.workspaceId returns 500)
{
"filters": "exposure.status = 'Open'",
"aggs": [{"name": "byWorkspace", "function": {"type": "TERMS", "field": "asset.workspaces.name", "size": 25}}]
}
securin-cve-enrichment.securin-threat-correlation.securin-remediation-guidance.securin-asset-triage.Securin__search_tools meta-tool to look up the right MCP tool by description.asset.* vs compositeAsset.*) matches the account's data model.getTopValues(field="exposure.status") to enumerate.aggregateExposureData (TERMS or DATE_HISTOGRAM) rather than raw listing.exposure.tags, exposure.customAttributes.* are discoverable via getApiFields.When this skill produces aggregated or multi-row data (counts, trends, distributions, comparisons, single-CVE reports), emit a chart/graph/infographic in the Securin brand palette (#712880 / #453983 / #542ade / #987bf7 / #d7cbfb), Lato font, light theme, with the Securin logo. Default colormap uses the monotone gradient defined in _shared/brand.md. Offer customization after delivery; never default to a different brand.
npx claudepluginhub securin-public/securin-skills --plugin securin-platformGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.