@ericrisco/rsc 0.1.51 → 0.1.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/manifest.json +4 -4
- package/package.json +1 -1
- package/skills/gamedev-multiplayer/SKILL.md +35 -48
- package/skills/gamedev-pathing/SKILL.md +20 -29
- package/skills/security-scan/SKILL.md +46 -67
- package/skills/security-scan/references/tools.md +0 -1
- package/skills/security-scan/references/triage.md +0 -1
package/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.52",
|
|
3
3
|
"counts": {
|
|
4
4
|
"skills": 258
|
|
5
5
|
},
|
|
@@ -1889,7 +1889,7 @@
|
|
|
1889
1889
|
},
|
|
1890
1890
|
{
|
|
1891
1891
|
"id": "gamedev-multiplayer",
|
|
1892
|
-
"description": "Use when adding multiplayer
|
|
1892
|
+
"description": "Use when adding multiplayer or netcode to a game — client-server vs P2P, server authority and anti-cheat, state replication vs RPCs, prediction and reconciliation, lag compensation, plus Godot 4 / Unity NGO / Unreal wiring. NOT single-player gameplay (that is `godot`, `unity`, `unreal`), NOT matchmaking or server hosting (that is `deployment`).",
|
|
1893
1893
|
"tags": [
|
|
1894
1894
|
"multiplayer",
|
|
1895
1895
|
"netcode",
|
|
@@ -1910,7 +1910,7 @@
|
|
|
1910
1910
|
},
|
|
1911
1911
|
{
|
|
1912
1912
|
"id": "gamedev-pathing",
|
|
1913
|
-
"description": "Use when
|
|
1913
|
+
"description": "Use when making NPCs, enemies, or units navigate a level — grid vs waypoint vs navmesh, A*/JPS, navmesh baking and agent radius, off-mesh links, steering, RVO crowd avoidance, and flow fields in Godot 4.x, Unity, Unreal. NOT collision response or character controllers (that is gamedev-physics), NOT aggro or difficulty design (that is game-design).",
|
|
1914
1914
|
"tags": [
|
|
1915
1915
|
"pathfinding",
|
|
1916
1916
|
"navmesh",
|
|
@@ -4175,7 +4175,7 @@
|
|
|
4175
4175
|
},
|
|
4176
4176
|
{
|
|
4177
4177
|
"id": "security-scan",
|
|
4178
|
-
"description": "Use when
|
|
4178
|
+
"description": "Use when automated scanners drive a security sweep of a repo or app — SAST, dependency/lockfile CVEs, secrets in the tree or git history, IaC misconfig — and the raw output has to become one deduped, exploitability-ranked report CI can gate on. NOT threat-modeling, OWASP design reasoning, or hand-authoring the fix (that is `secure-coding`).",
|
|
4179
4179
|
"tags": [
|
|
4180
4180
|
"security",
|
|
4181
4181
|
"sast",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gamedev-multiplayer
|
|
3
|
-
description: "Use when adding multiplayer
|
|
3
|
+
description: "Use when adding multiplayer or netcode to a game — client-server vs P2P, server authority and anti-cheat, state replication vs RPCs, prediction and reconciliation, lag compensation, plus Godot 4 / Unity NGO / Unreal wiring. NOT single-player gameplay (that is `godot`, `unity`, `unreal`), NOT matchmaking or server hosting (that is `deployment`)."
|
|
4
4
|
tags: [multiplayer, netcode, replication, networking, prediction, authority]
|
|
5
5
|
recommends: [godot, unity, unreal, gamedev-physics]
|
|
6
6
|
profiles: [full]
|
|
@@ -14,6 +14,16 @@ topology, put authority in the right place, replicate the right state, and hide
|
|
|
14
14
|
opening the door to cheaters. This skill owns the *networking* decisions; the engine skills own
|
|
15
15
|
the local gameplay those decisions sit on top of.
|
|
16
16
|
|
|
17
|
+
Route elsewhere when the ask is not netcode:
|
|
18
|
+
|
|
19
|
+
| The ask | Route to | Why not here |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| Single-player movement, AI, input, animation, save files | [`godot`](../godot/SKILL.md) / [`unity`](../unity/SKILL.md) / [`unreal`](../unreal/SKILL.md) | The engine skill owns local gameplay; no network dimension. |
|
|
22
|
+
| Physics determinism, collision, character controllers | [`gamedev-physics`](../gamedev-physics/SKILL.md) | Netcode *consumes* determinism; it does not own the physics fix. |
|
|
23
|
+
| Matchmaking, lobby backend, dedicated-server hosting, relays, DB, game-server CI | [`deployment`](../deployment/SKILL.md) | Running the fleet, not designing the in-game net layer. |
|
|
24
|
+
| Web realtime — chat, presence, a generic WebSocket app | [`webhooks`](../webhooks/SKILL.md) | Not a game world/simulation. |
|
|
25
|
+
| General threat modeling, authz review | [`secure-coding`](../secure-coding/SKILL.md) | This skill keeps only the game-specific anti-cheat controls. |
|
|
26
|
+
|
|
17
27
|
## Version contract — read first
|
|
18
28
|
|
|
19
29
|
Target the current APIs. **Never emit these deprecated / removed APIs:**
|
|
@@ -30,19 +40,6 @@ community UNet-like fork), say so; this skill targets first-party NGO. In NGO 2.
|
|
|
30
40
|
`[ServerRpc]` / `[ClientRpc]` still compile (and enforce `…ServerRpc` / `…ClientRpc` method-name
|
|
31
41
|
suffixes) — cover them but prefer the unified form on new code.
|
|
32
42
|
|
|
33
|
-
## Fires on / When NOT
|
|
34
|
-
|
|
35
|
-
**Fires on:** "how do I sync players", replication, netcode, RPCs, authority, online co-op or PvP,
|
|
36
|
-
"client and server disagree", rubber-banding / teleporting players, prediction & reconciliation,
|
|
37
|
-
lag compensation, tick rate / send rate, spawning networked objects, "the client can cheat".
|
|
38
|
-
|
|
39
|
-
**When NOT (route away):**
|
|
40
|
-
|
|
41
|
-
- Single-player movement, AI, input, animation, save files → the engine skill: `godot`, `unity`, `unreal`.
|
|
42
|
-
- Physics determinism, collision, character controllers → `gamedev-physics` (netcode *consumes* it).
|
|
43
|
-
- Matchmaking service, lobby backend, dedicated-server hosting/orchestration, relays, DB → `deployment`.
|
|
44
|
-
- Web realtime (chat, presence, generic WebSocket app) that is not a game world → `webhooks` / a backend skill.
|
|
45
|
-
|
|
46
43
|
## Topologies & authority
|
|
47
44
|
|
|
48
45
|
Pick the topology first; everything else follows from it.
|
|
@@ -61,7 +58,8 @@ requests), never results. **Never trust the client:** the client cannot set its
|
|
|
61
58
|
score, currency, or hit results — it *asks*, the server *decides*, everyone else *observes*. A client
|
|
62
59
|
that says "I moved to X / I did 40 damage / I have 999 gold" is either lagging or cheating; treat both
|
|
63
60
|
the same. The one thing a client legitimately owns is its own input and, by convention, cosmetic-only
|
|
64
|
-
state. See references/prediction-and-latency.md for how to
|
|
61
|
+
state. See **[references/prediction-and-latency.md](references/prediction-and-latency.md)** for how to
|
|
62
|
+
keep this responsive.
|
|
65
63
|
|
|
66
64
|
## State replication vs RPCs
|
|
67
65
|
|
|
@@ -88,7 +86,7 @@ is the #1 cause of "it works for the host but not the client" bugs.
|
|
|
88
86
|
## The hard problems
|
|
89
87
|
|
|
90
88
|
Latency (round-trip time, RTT) is the enemy; jitter and packet loss make it worse. Four techniques,
|
|
91
|
-
covered in depth in **references/prediction-and-latency.md**:
|
|
89
|
+
covered in depth in **[references/prediction-and-latency.md](references/prediction-and-latency.md)**:
|
|
92
90
|
|
|
93
91
|
1. **Client-side prediction** — the owning client applies its own input *immediately* instead of waiting a
|
|
94
92
|
full RTT for the server, so local movement feels instant.
|
|
@@ -140,7 +138,8 @@ func request_fire(target: Vector3) -> void:
|
|
|
140
138
|
- `MultiplayerSynchronizer` streams a chosen property list (position, etc.) from the authority to peers;
|
|
141
139
|
set its replication interval and visibility (`set_visibility_for(peer, bool)`) to scope bandwidth.
|
|
142
140
|
- `MultiplayerSpawner` replicates instancing of scenes under a path so late peers get existing objects.
|
|
143
|
-
- Details, prediction wiring, and the full player-scene pattern:
|
|
141
|
+
- Details, prediction wiring, and the full player-scene pattern:
|
|
142
|
+
**[references/godot-high-level-multiplayer.md](references/godot-high-level-multiplayer.md)**.
|
|
144
143
|
|
|
145
144
|
### Unity — Netcode for GameObjects
|
|
146
145
|
|
|
@@ -168,7 +167,8 @@ public class Player : NetworkBehaviour {
|
|
|
168
167
|
- `NetworkVariable<T>(value, readPerm, writePerm)` — `NetworkVariableWritePermission.Server` (default) vs
|
|
169
168
|
`.Owner`; subscribe via `OnValueChanged`. Use `NetworkTransform` for pos/rot sync.
|
|
170
169
|
- Prefer the unified `[Rpc(SendTo.X)]`; legacy `[ServerRpc]`/`[ClientRpc]` still work but need the
|
|
171
|
-
method-name suffixes. Full patterns:
|
|
170
|
+
method-name suffixes. Full patterns:
|
|
171
|
+
**[references/unity-and-unreal-netcode.md](references/unity-and-unreal-netcode.md)**.
|
|
172
172
|
|
|
173
173
|
### Unreal — Actor replication
|
|
174
174
|
|
|
@@ -196,7 +196,8 @@ void AMyPawn::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& Out) const {
|
|
|
196
196
|
- **Relevancy** keeps bandwidth sane: `NetCullDistanceSquared`, `bAlwaysRelevant`, `IsNetRelevantFor`, and
|
|
197
197
|
dormancy (`SetNetDormancy`) stop replicating actors a client can't perceive. Movement replicates via
|
|
198
198
|
`CharacterMovementComponent`, which already does prediction+reconciliation for you.
|
|
199
|
-
- RepNotify vs Multicast, GAS/Network Prediction notes:
|
|
199
|
+
- RepNotify vs Multicast, GAS/Network Prediction notes:
|
|
200
|
+
**[references/unity-and-unreal-netcode.md](references/unity-and-unreal-netcode.md)**.
|
|
200
201
|
|
|
201
202
|
## Security / anti-cheat basics
|
|
202
203
|
|
|
@@ -219,32 +220,18 @@ void AMyPawn::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& Out) const {
|
|
|
219
220
|
- Always test **with simulated latency and packet loss**, not just on localhost — localhost hides every
|
|
220
221
|
prediction/reconciliation bug. Test the client path, not only the host's.
|
|
221
222
|
|
|
222
|
-
##
|
|
223
|
-
|
|
224
|
-
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
- **`deployment`** — dedicated-server hosting, matchmaking/lobby backend, relays, and CI for game servers.
|
|
238
|
-
- **`secure-coding`** — general threat modeling; this skill keeps only the game-specific anti-cheat controls.
|
|
239
|
-
|
|
240
|
-
## Checklist
|
|
241
|
-
|
|
242
|
-
- [ ] Topology chosen (dedicated / listen / P2P) and the *same code* runs on server and listen host.
|
|
243
|
-
- [ ] Server-authoritative: clients send intent only; server validates and owns all gameplay state.
|
|
244
|
-
- [ ] Each networked value is either replicated (state/nouns) or an RPC (events/verbs) — not the wrong one.
|
|
245
|
-
- [ ] Ownership/authority set explicitly per object; authority-only logic guarded on the host.
|
|
246
|
-
- [ ] Owning-client movement predicted + reconciled; remote entities snapshot-interpolated.
|
|
247
|
-
- [ ] Hitscan uses server-side lag compensation; simulation on a fixed tick, decoupled from render FPS.
|
|
248
|
-
- [ ] Only need-to-know state replicated per client (relevancy/visibility scoped); RPCs rate-limited.
|
|
249
|
-
- [ ] Tested with simulated latency + packet loss across multiple instances, exercising the client path.
|
|
250
|
-
- [ ] No banned APIs (UNet/HLAPI, Godot 3.x `master`/`puppet`/`rset`, `Tick`-polled Unreal replication).
|
|
223
|
+
## Anti-patterns
|
|
224
|
+
|
|
225
|
+
| Anti-pattern | Why it bites | Do instead |
|
|
226
|
+
| --- | --- | --- |
|
|
227
|
+
| Writing net code before the topology is chosen | Authority and cost model change everything downstream | Pick dedicated / listen / P2P first, and make the *same code* run on server and listen host |
|
|
228
|
+
| Trusting a client-reported result (health, position, score, hit) | That is the cheat surface, and lag looks identical to cheating | Clients send intent only; the server validates and owns all gameplay state |
|
|
229
|
+
| RPCing state that must stay consistent | A dropped unreliable event desyncs that client permanently | Replicate nouns (state), RPC verbs (events) — replicated values self-correct |
|
|
230
|
+
| Ownership/authority left implicit | The #1 cause of "works for the host, breaks for the client" | Set authority/ownership explicitly on spawn |
|
|
231
|
+
| Forgetting the listen-server host is also a client | Authority-only logic double-executes on the host | Guard it behind `is_server()` / `HasAuthority()` |
|
|
232
|
+
| Making the owning client wait a full RTT for its own input | Movement feels sluggish and unresponsive | Predict locally + reconcile; snapshot-interpolate remote entities |
|
|
233
|
+
| Client-side hit detection for hitscan | Trivially spoofed, and unfair to the higher-ping shooter | Server-side lag compensation: rewind to the shooter's render time |
|
|
234
|
+
| Tying simulation to render FPS | Sim diverges between machines at different frame rates | Fixed timestep on the sim, interpolate on the render |
|
|
235
|
+
| Replicating everything, every tick, to everyone | Melts bandwidth and leaks wallhack fuel | Scope by relevancy/visibility and send rate; rate-limit RPCs |
|
|
236
|
+
| Testing only on localhost | 0 ms RTT masks the exact desync/rubber-band bugs players will hit | Inject latency + packet loss across instances, exercising the client path |
|
|
237
|
+
| Emitting UNet/HLAPI, Godot 3.x `master`/`puppet`/`rset`, or `Tick`-polled Unreal replication | Removed or legacy — it will not compile or will silently underperform | The current APIs in the version contract above |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gamedev-pathing
|
|
3
|
-
description: "Use when
|
|
3
|
+
description: "Use when making NPCs, enemies, or units navigate a level — grid vs waypoint vs navmesh, A*/JPS, navmesh baking and agent radius, off-mesh links, steering, RVO crowd avoidance, and flow fields in Godot 4.x, Unity, Unreal. NOT collision response or character controllers (that is gamedev-physics), NOT aggro or difficulty design (that is game-design)."
|
|
4
4
|
tags: [pathfinding, navmesh, navigation, steering, a-star]
|
|
5
5
|
recommends: [godot, unity, unreal, gamedev-physics]
|
|
6
6
|
profiles: [full]
|
|
@@ -102,7 +102,8 @@ Combine either as a **weighted sum** (simple) or **priority/arbitration** (avoid
|
|
|
102
102
|
**Local avoidance (RVO / ORCA):** each agent picks a velocity that is collision-free assuming neighbours
|
|
103
103
|
share the burden (*reciprocal* — hence no oscillating "dance"). This is avoidance, **not** collision
|
|
104
104
|
*response*: it changes intended velocity *before* moving; the physics/collision solver is a separate,
|
|
105
|
-
last-resort backstop (→ `gamedev-physics`). For dense crowds use the
|
|
105
|
+
last-resort backstop (→ [`gamedev-physics`](../gamedev-physics/SKILL.md)). For dense crowds use the
|
|
106
|
+
engine's crowd/avoidance system.
|
|
106
107
|
|
|
107
108
|
**Flow fields** — for **many agents → one (or few) goals** (RTS swarm, tower-defense creeps): run one
|
|
108
109
|
**Dijkstra from the goal** over the grid to build a cost/integration field, derive a per-cell direction
|
|
@@ -182,30 +183,26 @@ AICon->MoveToActor(TargetActor, /*AcceptanceRadius*/ 50.f); // or MoveToLocati
|
|
|
182
183
|
4. Costs/holes: **`NavModifierVolume`** + `NavArea` classes. Off-mesh: **`NavLinkProxy`**. Crowd
|
|
183
184
|
avoidance: enable the **Detour Crowd** manager (or `DetourCrowdAIController`) for RVO on many agents.
|
|
184
185
|
|
|
185
|
-
> High-level BT *design* (states, aggro, difficulty) is `game-design
|
|
186
|
+
> High-level BT *design* (states, aggro, difficulty) is [`game-design`](../game-design/SKILL.md); this skill wires the BT's
|
|
186
187
|
> movement/EQS tasks to navigation, not the decision tree's semantics.
|
|
187
188
|
|
|
188
|
-
##
|
|
189
|
+
## Anti-patterns
|
|
189
190
|
|
|
190
|
-
-
|
|
191
|
-
- Bake covers **static** geometry; runtime-spawned meshes need a rebake, a carving obstacle, or a nav link.
|
|
192
|
-
- Path returns empty when start/end are **off the navmesh** or in disconnected islands — snap to nearest poly and check reachability first.
|
|
193
|
-
- Avoidance (RVO) ≠ collision (physics). Agents can still overlap under pressure; that is expected, not a physics bug.
|
|
194
|
-
- Off-mesh links are **directional and manual** — a jump-down link does not imply a jump-up link.
|
|
195
|
-
- Smooth grid paths (funnel / string-pull) or agents walk visible zig-zag staircases.
|
|
196
|
-
|
|
197
|
-
## Anti-patterns / rationalizations → STOP
|
|
198
|
-
|
|
199
|
-
| Rationalization | Reality / do instead |
|
|
191
|
+
| Anti-pattern | Do instead |
|
|
200
192
|
| --- | --- |
|
|
201
|
-
|
|
|
202
|
-
|
|
|
203
|
-
|
|
|
204
|
-
|
|
|
205
|
-
|
|
|
206
|
-
|
|
|
207
|
-
|
|
|
208
|
-
|
|
|
193
|
+
| Running a full A* every frame | Path on goal-change (or throttled) and steer between frames — per-frame search melts CPU at scale. |
|
|
194
|
+
| One navmesh bake shared by every unit | Radius/height differ; bake per agent size or use agent-type profiles. |
|
|
195
|
+
| Baking with a placeholder agent radius | Bake with the real radius — mismatch is the top "stuck in doorways / clipping walls" cause. |
|
|
196
|
+
| Treating agents that clip through each other as a physics bug | Missing **local avoidance**; enable RVO/crowd — that is the navigation layer. |
|
|
197
|
+
| Expecting RVO to prevent every overlap | Avoidance ≠ collision. Agents can still overlap under pressure; that is expected, not a physics bug. |
|
|
198
|
+
| Expecting a **static** bake to see runtime-spawned geometry | Set Dynamic runtime generation / rebake, or add a carving obstacle or nav link. |
|
|
199
|
+
| Hand-rolling your own grid A* in Unity/Unreal | Reinvents the built-in navmesh; use `NavMeshAgent` / `AAIController::MoveTo`. |
|
|
200
|
+
| 500 zombies each running A* to the player | That's a **flow field**: one Dijkstra from the goal, agents sample cells. |
|
|
201
|
+
| Setting `agent.destination` and reading the path the same frame | Path is async (`pathPending`); gate on it before trusting `remainingDistance`. |
|
|
202
|
+
| Inflating `h` because a bigger heuristic seems smarter | Over-estimating `h` breaks A* optimality; keep it admissible (or weight it *knowingly*). |
|
|
203
|
+
| Trusting a path query that came back empty | Start/end are **off the navmesh** or in disconnected islands — snap to the nearest poly and check reachability first. |
|
|
204
|
+
| Assuming an off-mesh link works both ways | Links are **directional and manual** — a jump-down link does not imply a jump-up link. |
|
|
205
|
+
| Feeding raw grid paths to the mover | Smooth them (funnel / string-pull) or agents walk visible zig-zag staircases. |
|
|
209
206
|
|
|
210
207
|
## Related skills
|
|
211
208
|
|
|
@@ -213,7 +210,7 @@ AICon->MoveToActor(TargetActor, /*AcceptanceRadius*/ 50.f); // or MoveToLocati
|
|
|
213
210
|
- [`unity`](../unity/SKILL.md) — Unity/C# project setup; here for the NavMesh + AI Navigation package details.
|
|
214
211
|
- [`unreal`](../unreal/SKILL.md) — UE5/Blueprint/C++; here for RecastNavMesh + AIController/BT/EQS wiring.
|
|
215
212
|
- [`gamedev-physics`](../gamedev-physics/SKILL.md) — collision *response*, rigidbodies, character controllers; steering decides intended velocity, physics resolves the contact.
|
|
216
|
-
- `game-design` — high-level enemy behaviour, aggro, encounter/difficulty design (what the AI *decides*, not how it *moves*).
|
|
213
|
+
- [`game-design`](../game-design/SKILL.md) — high-level enemy behaviour, aggro, encounter/difficulty design (what the AI *decides*, not how it *moves*).
|
|
217
214
|
|
|
218
215
|
## Checklist
|
|
219
216
|
|
|
@@ -234,9 +231,3 @@ the project's navigation decisions in `02-DOCS/wiki/stack/gamedev-pathing.md` (i
|
|
|
234
231
|
`02-DOCS/wiki/index.md`): engine + version, chosen representation, bake settings (agent sizes, cell
|
|
235
232
|
size), avoidance/crowd choice, custom links/areas. Read it first on every use; bump its `Updated` date
|
|
236
233
|
when a convention changes. No `02-DOCS/` layer? Skip silently — conventions are *recorded, not gated*.
|
|
237
|
-
|
|
238
|
-
## See Also — local references (read when)
|
|
239
|
-
|
|
240
|
-
- `references/search-algorithms.md` — representations, A*/Dijkstra/JPS/HPA* pseudocode, heuristics & admissibility, tie-breaking, any-angle, funnel smoothing.
|
|
241
|
-
- `references/navmesh-workflow.md` — bake-parameter table, areas/costs, off-mesh links, obstacles vs carving vs partial rebake, per-engine baking, debugging.
|
|
242
|
-
- `references/steering-and-avoidance.md` — steering primitives, path following, boids weights, RVO/ORCA intuition, crowds, flow-field construction.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: security-scan
|
|
3
|
-
description: "Use when
|
|
3
|
+
description: "Use when automated scanners drive a security sweep of a repo or app — SAST, dependency/lockfile CVEs, secrets in the tree or git history, IaC misconfig — and the raw output has to become one deduped, exploitability-ranked report CI can gate on. NOT threat-modeling, OWASP design reasoning, or hand-authoring the fix (that is `secure-coding`)."
|
|
4
4
|
tags: [security, sast, sca, secrets, scanning, owasp]
|
|
5
5
|
recommends: [secure-coding, github-actions, verify]
|
|
6
6
|
origin: risco
|
|
@@ -15,40 +15,28 @@ finding comes from a **tool run**, not a hunch — if you are reasoning about a
|
|
|
15
15
|
design or hand-writing a fix, that is [`secure-coding`](../secure-coding/SKILL.md),
|
|
16
16
|
not this skill.
|
|
17
17
|
|
|
18
|
-
Your job is orchestration + triage
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
| Class | What it catches | Primary tool | Backup / fast pass |
|
|
42
|
-
|---|---|---|---|
|
|
43
|
-
| **SAST** | injection, XSS, path traversal in *first-party* code | Semgrep | — |
|
|
44
|
-
| **SCA / deps** | known CVEs in dependency manifests + lockfiles | osv-scanner | `npm audit`, `pip-audit` |
|
|
45
|
-
| **Secrets** | credentials in the tree **or git history** | gitleaks (speed) | TruffleHog (depth + live verification) |
|
|
46
|
-
| **Misconfig / IaC** | Dockerfile, k8s, Terraform, exposed config | Trivy `config` | Semgrep rulesets |
|
|
47
|
-
|
|
48
|
-
### Tool selection by ecosystem
|
|
49
|
-
|
|
50
|
-
Pick by what is in the repo. This is the real branch point — match the tool to
|
|
51
|
-
the manifest, do not run everything everywhere.
|
|
18
|
+
Your job is orchestration + triage: every finding traces to a scanner run with a
|
|
19
|
+
`ruleId` and a source location, so the output is reproducible. Not eyeballing
|
|
20
|
+
code, not authoring patches.
|
|
21
|
+
|
|
22
|
+
**Read-only by default.** Scan, triage, report. Apply fixes (version bumps,
|
|
23
|
+
rotation, `.gitignore` edits) only when the user asks — a security sweep that
|
|
24
|
+
silently mutates the tree destroys the evidence and the trust.
|
|
25
|
+
|
|
26
|
+
**Pin and verify your scanners.** Exact versions, verified checksums/SHAs, never
|
|
27
|
+
`@latest` GitHub Actions. In **March 2026 Trivy was supply-chain compromised** —
|
|
28
|
+
malicious releases `v0.69.4/0.69.5/0.69.6` and a hijacked
|
|
29
|
+
`aquasecurity/trivy-action` exfiltrated CI secrets. Your scanner runs with repo +
|
|
30
|
+
CI-secret access; an unpinned scanner is itself the attack surface.
|
|
31
|
+
|
|
32
|
+
## Scan classes and tool selection
|
|
33
|
+
|
|
34
|
+
Four classes: **SAST** (injection, XSS, path traversal in *first-party* code),
|
|
35
|
+
**SCA / deps** (known CVEs in dependency manifests + lockfiles), **Secrets**
|
|
36
|
+
(credentials in the tree **or git history**), **Misconfig / IaC** (Dockerfile,
|
|
37
|
+
k8s, Terraform, exposed config). Pick tools by what is in the repo. This is the
|
|
38
|
+
real branch point — match the tool to the manifest, do not run everything
|
|
39
|
+
everywhere.
|
|
52
40
|
|
|
53
41
|
| Repo contains | SAST | SCA | Secrets | Misconfig |
|
|
54
42
|
|---|---|---|---|---|
|
|
@@ -56,15 +44,17 @@ the manifest, do not run everything everywhere.
|
|
|
56
44
|
| Python (`poetry.lock`/`requirements.txt`) | Semgrep | osv-scanner + `pip-audit` (fast) | gitleaks → TruffleHog | Trivy |
|
|
57
45
|
| Go (`go.mod`/`go.sum`) | Semgrep | osv-scanner (+ `govulncheck` for reachability) | gitleaks | Trivy |
|
|
58
46
|
| Containers (`Dockerfile`, images) | — | Trivy `fs`/`image` | Trivy `--scanners secret` | Trivy `config` |
|
|
59
|
-
| IaC (Terraform/k8s/Helm) | Semgrep (IaC rules) | — | gitleaks | Trivy `config
|
|
47
|
+
| IaC (Terraform/k8s/Helm) | Semgrep (IaC rules) | — | gitleaks | Trivy `config`, Semgrep rulesets |
|
|
60
48
|
| Monorepo (mixed) | Semgrep `auto` | osv-scanner (multi-ecosystem) | gitleaks → TruffleHog | Trivy |
|
|
61
49
|
|
|
62
50
|
Full install (pinned), flag matrix, and suppression syntax: `references/tools.md`.
|
|
63
51
|
|
|
64
52
|
## Run recipes
|
|
65
53
|
|
|
66
|
-
All recipes emit SARIF or JSON
|
|
67
|
-
|
|
54
|
+
All recipes emit SARIF (or JSON you normalize to it) — a common schema is what
|
|
55
|
+
lets you merge four tools, dedupe, and feed one artifact into CI instead of four
|
|
56
|
+
incompatible logs. **Pin the version shown**; the placeholders below mark where
|
|
57
|
+
to lock an exact tag/digest.
|
|
68
58
|
|
|
69
59
|
### SAST — Semgrep
|
|
70
60
|
|
|
@@ -107,10 +97,10 @@ gitleaks detect --redact --report-format sarif --report-path secrets.sarif
|
|
|
107
97
|
trufflehog git file://. --only-verified --json > trufflehog.json
|
|
108
98
|
```
|
|
109
99
|
|
|
110
|
-
### Misconfig / IaC — Trivy (PINNED — see the caveat)
|
|
100
|
+
### Misconfig / IaC — Trivy (PINNED — see the caveat above)
|
|
111
101
|
|
|
112
102
|
Trivy scans filesystems, images, and IaC and finds transitive CVEs `npm audit`
|
|
113
|
-
misses.
|
|
103
|
+
misses.
|
|
114
104
|
|
|
115
105
|
```bash
|
|
116
106
|
# Pin the EXACT version (NOT v0.69.4/.5/.6 — those were the malicious releases).
|
|
@@ -200,17 +190,17 @@ Emit one `security-scan-report.json` — the machine-checkable contract CI gates
|
|
|
200
190
|
|
|
201
191
|
## Anti-patterns
|
|
202
192
|
|
|
203
|
-
|
|
|
193
|
+
| Anti-pattern | Do instead |
|
|
204
194
|
|---|---|
|
|
205
|
-
|
|
|
206
|
-
|
|
|
207
|
-
|
|
|
208
|
-
|
|
|
209
|
-
|
|
|
210
|
-
|
|
|
211
|
-
|
|
|
212
|
-
|
|
|
213
|
-
|
|
|
195
|
+
| Pulling `aquasecurity/trivy-action@latest` because it is the official action | March 2026: a hijacked tag stole CI secrets. Pin a full SHA, verify provenance. |
|
|
196
|
+
| Treating every scanner finding as a bug to fix | Most are noise. Rank by reachable + exposed + sensitive sink; report the few that matter. |
|
|
197
|
+
| Calling the repo clean after scanning only the working tree | History holds the deleted keys. Scan git history; a removed-in-HEAD key is still leaked and live. |
|
|
198
|
+
| Declaring deps fine because `npm audit` is clean | Native auditors miss transitive CVEs. Run osv-scanner/Trivy too; native is the fast pass, not the only pass. |
|
|
199
|
+
| Committing a blanket `.semgrepignore` to quiet CI | A blanket ignore hides the next real bug. Suppress per-finding with a written justification + expiry. |
|
|
200
|
+
| Deleting a verified key from the file and moving on | Deleting ≠ safe. Rotate the credential first, then scrub history. The committed value is already compromised. |
|
|
201
|
+
| Taking the SARIF `level` as the severity | Tools disagree. Normalize to one scale before you rank or gate. |
|
|
202
|
+
| Dumping all four tool outputs in the PR for the reviewer to sort | The reviewer won't. Merge, dedupe, rank, and emit one report. |
|
|
203
|
+
| Letting the scan auto-fix the deps it finds | Read-only by default. Propose bumps; apply only when asked — never mutate during a sweep. |
|
|
214
204
|
|
|
215
205
|
## Project grounding (02-DOCS + CLAUDE.md)
|
|
216
206
|
|
|
@@ -218,23 +208,12 @@ In a project with a `02-DOCS/` layer (the [`harness`](../harness/SKILL.md)
|
|
|
218
208
|
Karpathy wiki), record the scanner choices, pinned versions, gate thresholds, and
|
|
219
209
|
any accepted-risk suppressions in `02-DOCS/wiki/stack/security-scan.md`, and index
|
|
220
210
|
it in `02-DOCS/wiki/index.md` (the Knowledge map; root `CLAUDE.md` keeps only a short
|
|
221
|
-
pointer to it). Read it first on every run so the
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
the scan on this.
|
|
211
|
+
pointer to it). Read it first on every run so the next agent inherits the pinned
|
|
212
|
+
tools and thresholds instead of re-deriving them. No `02-DOCS/`? Skip silently.
|
|
213
|
+
Conventions are recorded, not gated — never block the scan on this.
|
|
225
214
|
|
|
226
215
|
## See Also
|
|
227
216
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
design it's secure-coding.*
|
|
232
|
-
- [`review`](../review/SKILL.md) — adversarial review of a diff against a spec.
|
|
233
|
-
- [`code-review`](../code-review/SKILL.md) — general correctness/quality review.
|
|
234
|
-
- [`verify`](../verify/SKILL.md) — the broader lint/type/test green gate this
|
|
235
|
-
feeds into.
|
|
236
|
-
- **References** — `references/tools.md` (pinned installs, flag matrix,
|
|
237
|
-
suppression syntax); `references/triage.md` (ranking rubric, dedupe keying,
|
|
238
|
-
severity map, full report schema).
|
|
239
|
-
</content>
|
|
240
|
-
</invoke>
|
|
217
|
+
Reviewing a diff rather than scanning a repo: [`code-review`](../code-review/SKILL.md)
|
|
218
|
+
for correctness and quality, [`review`](../review/SKILL.md) for adversarial review
|
|
219
|
+
against a spec.
|
|
@@ -95,4 +95,3 @@ trivy image --format sarif --output trivy-img.sarif <pinned-image@sha256:...>
|
|
|
95
95
|
- Every recipe emits SARIF 2.1.0 so findings merge into one report. Where a tool
|
|
96
96
|
only emits native JSON (`npm audit`, `pip-audit`, TruffleHog), normalize it to
|
|
97
97
|
the report schema in `triage.md` rather than gating on its raw shape.
|
|
98
|
-
</content>
|