should-i-care
Single-CVE applicability triage. The user asks "am I affected by CVE-X?" and the skill returns a reasoned verdict evaluated against the user's environment profile.
The value is NOT product matching. Scanners do that via CPE. The value is condition evaluation: does the vulnerability actually apply given the specific conditions in the user's environment: deployment model (OWA vs. Exchange Online), protocol state (RC4 still allowed), memory protections (ASLR disabled), a feature toggled on or off. This is the step a CPE match cannot perform. It is the manual step a human does after a scanner flags a hit.
Core principle
Anchor on the canonical CVE record for identity (what the CVE is). Evaluate conditions (under what circumstances it applies) against the user's environment profile. Return one of three verdicts with a full, source-backed reasoning chain.
The reasoning chain is the product. It is the user's basis for cross-checking. I can be wrong about condition research. The output must always expose its logic so the user can verify.
Output language
Answer in the user's language. The structural examples in this skill are written in English to fix the shape of the output; the answer itself follows whatever language the user is writing in.
The environment file
The skill reads and maintains a single environment file at a fixed path: ~/.config/should-i-care/environment.md. The skill does not look in the working directory and does not look in the skill directory. If the file is absent, see First-run below.
This file is skill-maintained state, not a document the user keeps beside a project. It has to be found again on every run regardless of which directory Claude Code was launched from, and it has to survive skill updates. Writing it into the working directory is non-deterministic: launch Claude Code somewhere else and the profile is not found, so the skill starts over from an empty inventory. Writing it into the skill directory is unsafe, since a skill update or a re-clone can overwrite it. A fixed user-level path avoids both, so the location is always ~/.config/should-i-care/environment.md.
The file has two layers.
Layer 1: Inventory
What is in the environment: product, version/build, deployment model. This is the cheap first gate. If the product is not present (including any product that implies the CVE's target component, see Component derivation below) the assessment ends as not affected (subject to the absence-of-evidence rule).
Exposure is an optional Layer 1 attribute. Values: internet-facing, internal, unsure. It is meaningful ONLY for entries that accept inbound connections: server services (web server, mail server, directory service, database) and network/appliance gear (VPN gateway, firewall, management interfaces). Do NOT ask for it or attach it to client devices, client operating systems, laptops, or mobile devices; those do not listen for inbound connections, so exposure says nothing about them. Apply the same discipline used for Layer 2 conditions: only ask when it moves the verdict or the urgency. Concretely, exposure is relevant only when BOTH of these hold: the affected entry is a service that accepts inbound connections, AND the CVE has a network-reachable vector. For a local-only vector (local privilege escalation, requires local access), exposure is irrelevant and must not be asked. When exposure is relevant but missing for the affected service, ask one closed question (internet-facing or internal?), then write it back to that inventory entry as a Layer 1 attribute with source and date via the normal write-back-with-confirmation path. Exposure sharpens urgency; it never by itself decides applicability (see Urgency tag).
Layer 2: Condition store
Discriminating settings: "OWA in use?", "RC4 allowed?", "ASLR disabled?", auth mode. Grows organically, one CVE at a time. Each condition carries:
valuelast_verified(date)source(e.g. user-confirmed)- volatility tag:
stableorvolatile - optional
notes(one short qualifier)
The written form in the file is a single Markdown table, one row per condition, with columns Condition | value | last_verified | source | volatility | notes. Write Layer 2 to environment.md as this table, not as nested bullet blocks, so the file stays scannable as conditions accumulate. The fields above are what each row holds; the table is how they are stored.
Do not confuse this storage table with the Condition | your state | Sources table in Layout A: that one presents a verdict in chat, this one stores conditions in the file. They are different tables for different purposes.
Format is plain Markdown. No CPE in the template. CPE may appear as an optional power-user field for one product if the user wants it; it is never required.
The user must never be required to hand-edit the file. Every change happens via write-back with confirmation (see below): the user confirms in chat, then I write the file directly on the local filesystem. The template exists so a curious user can read what happened; the path to every change is the chat. Because the skill runs on an agent with a local filesystem, the write-back is automatic and persists across sessions.
Assessment log (optional)
An optional ## Assessment log section records verdicts chronologically, one entry per assessment: date, CVE ID, the verdict, and a one-line basis (why it was cleared or flagged). It is written via the same write-back-with-confirmation path. It is the user's audit trail and the "why was this cleared" memory for future assessments. Entries are appended, never silently rewritten.
Component derivation at the gate
Do not match the CVE's product name literally against the inventory text. Users write what they know ("iPhone 17", "Active Directory", "Exchange"); CVEs target what runs underneath ("iOS", "Kerberos" / "NTLM" / "LSASS", "Outlook Web App"). A literal string match would wrongly clear the user, exactly the silent false-negative the verdict asymmetry exists to prevent.
An inventory product pulls in the platform, standard components, and subsystems it runs. The gate matches against that derived set, not the literal name. Examples:
- iPhone → iOS
- Active Directory → Kerberos, NTLM, LDAP, AD roles/services
- Windows Server → its installable roles
- Exchange Server → OWA, transport, mailbox role
This derivation is factual and verifiable, not speculative: that an iPhone runs iOS is lookupable, not a guess. Expose the derivation in the reasoning ("your inventory lists iPhone 17, which runs iOS; the CVE targets iOS, so it is relevant") in keeping with the traceable-reasoning principle.
Keep the derivation conservative: immediate components and direct subsystems, not deep transitive chains. Do not walk Exchange → .NET → Windows → ... unless the CVE specifically targets that link. When in doubt, let the CVE through the gate and resolve it in the condition step. Passing a non-applicable CVE into condition analysis is cheap; wrongly dropping an applicable one is the dangerous error.
Crucially, derivation is ONLY the gate. That a component is present (AD implies Kerberos) does not mean the discriminating condition is met (whether RC4 is still allowed as a Kerberos etype is a Layer 2 condition that the mere presence of AD does not answer). Derivation gets the CVE past "is the affected thing even here"; the normal condition mechanism then decides whether it actually fires under the user's specific settings. If a derived component's deciding detail (e.g. the exact iOS build) is missing, that is a normal assumption-disclosure / write-back moment, not a reason to verdict on the spot.
Caveat for commonly embedded libraries and runtimes (libxml2, OpenSSL, zlib, curl, the Go standard library, Electron, and similar): if the inventory holds higher-level products that plausibly bundle the target, do NOT clear on absence. Route to needs-verifica