Mmcp.market

sg-deceptive-reachability-auditor skill

by anyshift-io·anyshift-io/sre-skills·17 stars·Apache-2.0

Audit a fleet of AWS security groups for the multi-hop lateral-movement path that no single ingress rule reveals. Builds a directed reachability graph from the SG-to-SG references (an ingress rule on SG B naming SG A means a host in A can reach B), adds an internet edge for every 0.0.0.0/0 rule, then composes those edges into the transitive closure from a named entry point (the internet, or a compromised host). Reports the shortest reachable path to the crown-jewel tier, the blast radius, and any pivot/hub SG that bridges otherwise-isolated regions, each ranked by severity with a fix. Its discipline is symmetric: on a segmented or orphaned fleet where the chain does NOT reach the crown jewel, it reports clean and names the boundary instead of fabricating a path. Then it states what the SG graph alone cannot answer (live host membership, route tables, NACLs, app-layer auth). Use when asked to review a security-group fleet for lateral movement, blast radius, or whether the internet can reach a sensitive tier. Vendor-neutral; runs offline against describe-security-groups + describe-instances JSON with no Anyshift account.

A97/100content scan

Is the sg-deceptive-reachability-auditor skill safe?

Clean: nothing in its files matched our rules. We read 39 files in the folder on 2026-09-28.

  • lowSKILL.md:1

    The description is over 1,024 characters, the limit agents read.

    1136 characters

Install the sg-deceptive-reachability-auditor skill

A skill is a folder. Copy it into your agent's skills folder and the agent loads it when the task matches its description.

git clone --depth 1 https://github.com/anyshift-io/sre-skills.git /tmp/sre-skills
mkdir -p ~/.claude/skills
cp -r /tmp/sre-skills/skills/sg-deceptive-reachability-auditor ~/.claude/skills/sg-deceptive-reachability-auditor
available in every project

In the Claude apps, zip the folder and upload it from the Skills settings. The folder on GitHub

The instructions your agent would load

SKILL.md as published, without the frontmatter. Read it on GitHub

sg-deceptive-reachability-auditor

Reachability-audit skill for a fleet of AWS security groups. Takes the describe-security-groups output for the fleet (plus describe-instances for the instance-to-SG membership), composes the SG-to-SG references into a directed graph, and answers one question a per-rule read cannot: from a named entry point, what can actually be reached, and does any path reach the crown-jewel tier. It returns the shortest path, the blast radius, and any pivot hub, ranked by severity, then names exactly where the SG graph stops being able to answer the question.

The job is a graph problem, and the whole point of the skill is the composition the graph makes visible. A per-rule read sees "app accepts from web" and "db accepts from app" as two individually fine rules and never assembles that internet -> web -> app -> db is one reachable path. In a fleet of 10-13 security groups, that chain is buried among scoped tiers (bastion, monitoring, ci, ssm) and app-fed leaves (cache, queue, logs), and the loud 0.0.0.0/0 rule on the front door draws the eye away from it. This skill composes the edges instead of clearing each rule in isolation.

When to invoke

radius, or "can the internet reach the database."

  • An agent is asked to review a security-group fleet for lateral movement, blast

reach a sensitive one transitively, not just directly.

  • A fleet is being shipped or changed and the question is whether a low-trust tier can

pivot to.

  • An incident assumes a host is compromised and the question is what that foothold can

confirmed against the actual edges rather than taken on trust.

  • A fleet looks segmented and the claim "the database is isolated" needs to be

What this skill reads, and what it does not

It reads the static configuration of a fleet of security groups plus the instance-to-SG membership. Both are EC2 control-plane reads (describe-security-groups, describe-instances). That is the entire input. The audit is correct and complete for what the SG graph can tell you, and it is explicit about the rest. Reachability-on-paper is not exploitability, and every audit ends by naming the joins it cannot make:

referenced SG; it does not mean an instance in that SG is running and serving. An empty SG is a path to nothing. Join: SG graph to the live ENIs/instances in each SG.

  • It does not confirm a live host is listening. An edge means an SG accepts the

path no matter what the ingress rules allow. Join: SG graph to the subnet route tables.

  • It does not read route tables. Two SGs on unrouted subnets are not on a routable

and can deny traffic the SG graph would allow. Join: SG graph to the subnet NACLs.

  • It does not read network ACLs. A NACL is a stateless layer below security groups

app token can stop a network-reachable hop from becoming access. Join: network reachability to the app-layer auth on each tier.

  • It does not read app-layer auth. A database password, an mTLS handshake, or an

Every audit ends by naming these. A clean (segmented) fleet still gets a boundary section, because a network-segmented fleet is not a proven-safe system.

The model

Build a directed graph over security groups. An edge A -> B exists when SG B has an ingress rule whose UserIdGroupPairs includes SG A (B accepts traffic from A), meaning a host in A can reach a host in B. A synthetic node internet has an edge internet -> X for every SG X with a 0.0.0.0/0 (or ::/0) ingress rule.

From the entry point named for the audit (internet, or a compromised instance id that resolves to that instance's SGs), compute the transitive closure with BFS. A visited set makes cycles terminate. The findings fall out of the closure.

The methodology, in order

1. Parse the fleet into edges

Before any judgment, turn the JSON into the graph:

another SG in the fleet is an incoming edge: referenced-SG -> this-SG. This is the step a naive read skips. The SG-reference arrays are where the chain lives.

  • For each SG, read its IpPermissions (ingress). Every UserIdGroupPairs entry naming

internet-facing: internet -> this-SG.

  • Every 0.0.0.0/0 / ::/0 IpRanges / Ipv6Ranges entry makes the SG

compromised host) resolves to a set of start SGs, and so a tier with no running host can be flagged as a path to nothing at the boundary.

  • Read describe-instances for the instance-to-SG membership, so the entry point (a

reads as internet -> web -> app -> db, not as a list of sg- ids.

  • Label each SG by its tier / Name tag, then GroupName, then GroupId, so the path

2. Compute the closure and the path (P1)

Run BFS from the entry's start set. The reachable set is the closure minus the start. If the crown-jewel tier is in the closure, compute the shortest path (fewest hops) to it and report it as the headline:

shortest path as an explicit ordered hop list (internet -> cdn -> waf -> gw -> app -> svc -> db). No single ingress rule is alarming; each tier accepting the tier in front of it is routine. The edges compose into one path a per-rule read never assembles. This is the lateral-movement chain the audit exists to surface, and on a needle fleet it is the primary finding, named end to end, not a footnote under the loud public rule.

  • P1 (critical) — a reachable path from the entry to the crown jewel. Report the

3. Report the blast radius (B1)

(distance >= 2 from the entry, i.e. beyond the directly-exposed front-door tier), report the full reachable set: the tiers a foothold at the entry can pivot to with no further misconfiguration. State explicitly whether the crown jewel is inside the radius. A fleet whose chain breaks after the first hop has no lateral reach and does not fire B1 — that distinction is load-bearing for the clean fleets.

  • B1 (high) — the blast radius. When the closure composes at least one lateral hop

4. Find the pivot hub (H1)

intermediate reachable SG, recompute the closure with that node removed. If its removal disconnects two or more mutually-isolated regions of the blast radius, it is a true pivot (an articulation point), not just an ordinary hop on a linear chain. A shared-services SG (monitoring, CI, a jump tier) that every tier references is exactly this shape: it quietly joins tiers that were never meant to reach each other. Do not report the entry node or the directly-internet-facing front door as a hub; those are a different auditor's finding.

  • H1 (high) — a pivot/hub SG bridging otherwise-isolated regions. For each

5. Stay quiet on the deceptive-clean fleet

This is the half of the skill that the naive read gets wrong in the other direction. A segmented, orphaned, or broken fleet where no path reaches the crown jewel is CLEAN, and the audit must say so instead of manufacturing a path. The same composition discipline is what proves it. Specifically:

accepts only an internal service-mesh CIDR, not the public SG) is not a reachable path. Do not report it as one.

  • An orphaned deep chain (the deep tiers reference each other, but the front tier

path and not the headline.

  • An intended public ALB taking 0.0.0.0/0 is the expected ingress, not the lateral

be spliced into a manufactured internet -> db route.

  • A disjoint data island (a public region and an unconnected private region) must not

the cut.

  • A broken mid-chain segment (the chain is cut at one hop) is not reachable across

about correctly-scoped tiers (bastion, monitoring, ci, ssm).

  • Do not drown the real finding, or the clean verdict, in a wall of low-value nitpicks

On a clean fleet the audit reports: no reachable path to the crown jewel, the bounded blast radius (and the boundary it cannot cross), and the join checks that would confirm the segmentation holds. It does not invent a critical.

More skills from anyshift-io/sre-skills

  • Aiam-deceptive-escalation-auditorAudit the union of every IAM policy attached to one principal for privilege-escalation paths that no single statement reveals, and for apparent escalations that are already neutralised. Resolves the effective permission set across all attached policies (Allow minus blanket Deny), then checks the cross-statement escalation combos (iam:PassRole + a compute-launch action, policy-rewrite-in-place, function-code hijack, self-attach admin, trust-policy rewrite + assume, credential minting for another identity), the wildcard grants (Action '*' on Resource '*', service-level wildcards, Allow+NotAction), and the trust-policy exposure. Its discipline is symmetric: it does NOT flag a PassRole combo killed by an explicit Deny, an Action '*' pinned to one bucket, an sts:AssumeRole whose target does not trust back, a mutation kit capped by a permissions-boundary Deny, or a cross-account assume sealed by an unsatisfiable Condition. Reports findings with severity and a fix, then names what a single principal's policies cannot answer (the privileges of a passed/assumed role, the permissions boundary, the org SCPs). Use when asked to audit an IAM policy, role, or user for escalation, over-broad grants, or "can this principal become admin." Vendor-neutral; runs offline against the policy JSON with no Anyshift account.
  • Akubectl-investigatorInvestigate a live or recent incident in a Kubernetes cluster. Anchor the window, bisect the change surface (rollouts, ConfigMaps/Secrets, RBAC, HPA/cluster changes, CronJobs), classify against four reference failure paths (OOM, DNS, cascading-failure, deploy-correlator), confirm the hypothesis with three independent signals, quantify blast radius, and propose mitigation before root cause. Use whenever an agent is asked "what is breaking in the cluster right now", "why did this pod/Deployment just page", "did the rollout cause Z", or to triage an active Kubernetes incident. Vendor-neutral by default (works with kubectl, kube-state-metrics, and whatever telemetry you have); an opt-in Anyshift integration is documented separately.
  • As3-estate-calibration-auditorAudit an estate of AWS S3 buckets for the one bucket that is genuinely publicly or cross-account exposed, without over-flagging the many buckets that READ as exposed but are neutralised. Resolves each bucket's EFFECTIVE verdict by composing four layers (Block Public Access x bucket policy x bucket ACL x access points), never one layer alone, then rolls the per-bucket verdicts up into an estate verdict. Its discipline is symmetric: BPA (RestrictPublicBuckets / BlockPublicPolicy) neutralises a Principal '*' policy but NOT a cross-account grant; IgnorePublicAcls kills a public-group ACL grant but NOT a cross-account canonical-user grant; a narrowing Condition (org id, ExternalId, SourceIp, access-point delegation) scopes a Principal '*' so it is not public. On a needle estate it names the ONE live bucket as the primary finding; on a clean estate it reports NO live exposure and does not manufacture findings. Then it states what the bucket configs alone cannot answer (per-object ACLs, CloudFront/CDN fronting, the trusted principals' identity policies, account-level BPA dependency, data sensitivity). Use when asked to review an S3 bucket fleet for public exposure, cross-account access, or whether the estate is clean. Vendor-neutral; runs offline against describe-bucket / get-bucket-policy / get-bucket-acl / list-access-points JSON with no Anyshift account.
  • Asqs-queue-auditorAudit a single AWS SQS queue's configuration for the misconfigurations that silently drop or re-deliver messages while every attribute reads as fine. Parses the GetQueueAttributes output (and the referenced dead-letter queue), checks the redrive path (DLQ present, maxReceiveCount band, DLQ-vs-source retention ordering), the message lifecycle (poison messages aging out before they reach the DLQ, default visibility timeout, short retention), and exposure (open resource policy, encryption at rest, FIFO dedup contract). Reports findings with severity and a recommendation, then names the boundary: the questions a single queue's config cannot answer (consumer processing time, live behaviour, the IAM union, the producers and consumers on either side). Use when asked to review, harden, or sanity-check an SQS queue, or to explain why messages are going missing. Vendor-neutral; runs offline against the queue attributes with no Anyshift account.

All agent skills → · MCP servers