mirror of
https://github.com/anthropics/claude-plugins-official.git
synced 2026-05-11 22:15:52 -03:00
code-modernization: harden writes a patch instead of editing legacy; make map/security guidance language-agnostic
- modernize-harden: never edits legacy/ anymore. Writes findings plus a reviewed unified diff to analysis/<system>/security_remediation.patch. A second security-auditor pass reviews each hunk (RESOLVES / PARTIAL / INTRODUCES-RISK) before presenting. The user reviews and applies the patch deliberately, then re-runs to verify. This makes every command consistent with the recommended deny Edit(legacy/**) workspace setting, so the README's exception note is gone. - modernize-map: restructure the parse-target list around three stack- agnostic principles (dispatcher targets are variables; code-storage joins live in config; entry points live in deployment descriptors), with COBOL/Java/web/CLI examples on equal footing rather than COBOL-dominant. Same protections against false dead-code findings, less stack-specific. - security-auditor agent: rephrase coverage items in stack-neutral terms (record layouts/temp datasets, resource ACLs, deployment scripts/job definitions, batch input records) so the checklist reads naturally for COBOL, Java EE, .NET, and web targets alike. - README: drop the harden exception note; describe the patch workflow.
This commit is contained in:
parent
22a1b25977
commit
5e4a45001d
@ -10,7 +10,7 @@ Legacy modernization fails most often not because the target technology is wrong
|
||||
assess → map → extract-rules → brief → reimagine | transform → harden
|
||||
```
|
||||
|
||||
The discovery commands (`assess`, `map`, `extract-rules`) build artifacts under `analysis/<system>/`. The `brief` command synthesizes them into an approval gate. The build commands (`reimagine`, `transform`) write new code under `modernized/`. The `harden` command audits and patches the legacy system. Each step has a dedicated slash command, and specialist agents (legacy analyst, business rules extractor, architecture critic, security auditor, test engineer) are invoked from within those commands — or directly — to keep the work honest.
|
||||
The discovery commands (`assess`, `map`, `extract-rules`) build artifacts under `analysis/<system>/`. The `brief` command synthesizes them into an approval gate. The build commands (`reimagine`, `transform`) write new code under `modernized/`. The `harden` command audits the legacy system and produces a reviewable remediation patch. Each step has a dedicated slash command, and specialist agents (legacy analyst, business rules extractor, architecture critic, security auditor, test engineer) are invoked from within those commands — or directly — to keep the work honest.
|
||||
|
||||
## Expected layout
|
||||
|
||||
@ -47,9 +47,7 @@ Greenfield rebuild from extracted intent rather than a structural port. Mines a
|
||||
Surgical, single-module strangler-fig rewrite. Plans first (HITL gate), then writes characterization tests via `test-engineer`, then an idiomatic target implementation under `modernized/<system>/<module>/`, proves equivalence by running the tests, and produces `TRANSFORMATION_NOTES.md` mapping legacy → modern with deliberate deviations called out. Reviewed by `architecture-critic`.
|
||||
|
||||
### `/modernize-harden <system-dir>`
|
||||
Security hardening pass on the **legacy** system: OWASP/CWE scan, dependency CVEs, secrets, injection. Spawns `security-auditor`. Produces `analysis/<system>/SECURITY_FINDINGS.md` ranked Critical / High / Medium / Low, then **patches Critical and High findings directly in `legacy/<system>/`** and re-scans to verify. Useful as a pre-modernization step when the legacy system will keep running in production during the migration.
|
||||
|
||||
> **Note:** `/modernize-harden` is the one command that edits `legacy/`. If you adopt the `deny: Edit(legacy/**)` workspace setting below, relax it for this command — or run hardening as a separate workstream against its own checkout.
|
||||
Security hardening pass on the **legacy** system: OWASP/CWE scan, dependency CVEs, secrets, injection. Spawns `security-auditor`. Produces `analysis/<system>/SECURITY_FINDINGS.md` ranked Critical / High / Medium / Low and a reviewed `analysis/<system>/security_remediation.patch` with minimal fixes for the Critical/High findings. The patch is reviewed by a second `security-auditor` pass before you see it. **Never edits `legacy/`** — you review and apply the patch yourself when ready, then re-run to verify. Useful as a pre-modernization step when the legacy system will keep running in production during the migration.
|
||||
|
||||
## Agents
|
||||
|
||||
@ -89,7 +87,7 @@ This plugin ships commands and agents, but modernization projects benefit from a
|
||||
}
|
||||
```
|
||||
|
||||
Adjust `legacy/` and `modernized/` to match your actual layout. The key invariants: `Edit` under `legacy/` is denied, and writes are scoped to `analysis/` (for documents) and `modernized/` (for the new code). The exception is `/modernize-harden`, which intentionally patches `legacy/` — see its note above.
|
||||
Adjust `legacy/` and `modernized/` to match your actual layout. The key invariants: `Edit` under `legacy/` is denied, and writes are scoped to `analysis/` (for documents) and `modernized/` (for the new code). Every command in this plugin respects this — `/modernize-harden` writes a patch to `analysis/` rather than editing `legacy/` in place.
|
||||
|
||||
## Typical Workflow
|
||||
|
||||
|
||||
@ -11,28 +11,29 @@ engineer can fix.
|
||||
|
||||
## Coverage checklist
|
||||
|
||||
Adapt to the target stack — web items don't apply to a batch COBOL system,
|
||||
mainframe items don't apply to a SPA. Work through what's relevant:
|
||||
Adapt to the target stack — web items don't apply to a batch system,
|
||||
terminal/screen items don't apply to a SPA. Work through what's relevant:
|
||||
|
||||
- **Injection** (SQL, NoSQL, OS command, LDAP, XPath, template, dynamic
|
||||
DB2 SQL, JCL/PARM injection) — trace every user-controlled input to every sink
|
||||
- **Injection** (SQL, NoSQL, OS command, LDAP, XPath, template) — trace every
|
||||
user-controlled input to every sink, including dynamic SQL and shell-outs
|
||||
- **Authentication / session** — hardcoded creds, weak session handling,
|
||||
missing auth checks on sensitive routes/transactions
|
||||
- **Sensitive data exposure** — secrets in source, weak crypto, PII/PAN/SSN in
|
||||
logs, cleartext data in copybooks/flat files
|
||||
missing auth checks on sensitive routes/transactions/jobs
|
||||
- **Sensitive data exposure** — secrets in source, weak crypto, PII in logs,
|
||||
cleartext sensitive data in record layouts, flat files, or temp datasets
|
||||
- **Access control** — IDOR, missing ownership checks, privilege escalation;
|
||||
for CICS: missing/permissive RACF transaction & resource definitions,
|
||||
unguarded admin transactions
|
||||
- **XSS / CSRF** — unescaped output, missing tokens (web targets only)
|
||||
- **Insecure deserialization** — pickle/yaml.load/ObjectInputStream on
|
||||
untrusted data
|
||||
missing/permissive resource ACLs (RACF profiles, IAM policies, file perms);
|
||||
unguarded admin functions
|
||||
- **XSS / CSRF** — unescaped output, missing tokens (web targets)
|
||||
- **Insecure deserialization** — untrusted data into pickle/yaml.load/
|
||||
`ObjectInputStream` or custom record parsers
|
||||
- **Vulnerable dependencies** — run `npm audit` / `pip-audit` /
|
||||
read manifests and flag versions with known CVEs
|
||||
- **SSRF / path traversal / open redirect** (web targets only)
|
||||
- **Input validation** — for CICS/3270: unvalidated BMS field input,
|
||||
missing length/range/format checks before file/DB writes
|
||||
- **SSRF / path traversal / open redirect** (web/network targets)
|
||||
- **Input validation** — missing length/range/format checks at trust
|
||||
boundaries (form/screen fields, API params, batch input records) before
|
||||
persistence or downstream calls
|
||||
- **Security misconfiguration** — debug mode, verbose errors, default creds,
|
||||
hardcoded passwords/userids in JCL, PROCs, or sign-on programs
|
||||
hardcoded credentials in deployment scripts, job definitions, or config
|
||||
|
||||
## Tooling
|
||||
|
||||
|
||||
@ -1,23 +1,26 @@
|
||||
---
|
||||
description: Security vulnerability scan + remediation — OWASP, CVE, secrets, injection
|
||||
description: Security vulnerability scan with a reviewable remediation patch — OWASP, CWE, CVE, secrets, injection
|
||||
argument-hint: <system-dir>
|
||||
---
|
||||
|
||||
Run a **security hardening pass** on `legacy/$1`: find vulnerabilities, rank
|
||||
them, and fix the critical ones.
|
||||
them, and produce a reviewable patch for the critical ones.
|
||||
|
||||
This command never edits `legacy/` — it writes findings and a proposed patch
|
||||
to `analysis/$1/`. The user reviews and applies (or not).
|
||||
|
||||
## Scan
|
||||
|
||||
Spawn the **security-auditor** subagent:
|
||||
|
||||
"Adversarially audit legacy/$1 for security vulnerabilities. Cover:
|
||||
OWASP Top 10 (injection, broken auth, XSS, SSRF, etc.), hardcoded secrets,
|
||||
vulnerable dependency versions (check package manifests against known CVEs),
|
||||
missing input validation, insecure deserialization, path traversal.
|
||||
For each finding return: CWE ID, severity (Critical/High/Med/Low), file:line,
|
||||
one-sentence exploit scenario, and recommended fix. Also run any available
|
||||
SAST tooling (npm audit, pip-audit, OWASP dependency-check) and include
|
||||
its raw output."
|
||||
"Adversarially audit legacy/$1 for security vulnerabilities. Cover what's
|
||||
relevant to the stack: injection (SQL/NoSQL/OS command/template), broken
|
||||
auth, sensitive data exposure, access control gaps, insecure deserialization,
|
||||
hardcoded secrets, vulnerable dependency versions, missing input validation,
|
||||
path traversal. For each finding return: CWE ID, severity
|
||||
(Critical/High/Med/Low), file:line, one-sentence exploit scenario, and
|
||||
recommended fix. Run any available SAST tooling (npm audit, pip-audit,
|
||||
OWASP dependency-check) and include its raw output."
|
||||
|
||||
## Triage
|
||||
|
||||
@ -28,19 +31,34 @@ Write `analysis/$1/SECURITY_FINDINGS.md`:
|
||||
|
||||
## Remediate
|
||||
|
||||
For each **Critical** and **High** finding, fix it directly in the source.
|
||||
Make minimal, targeted changes. After each fix, add a one-line entry under
|
||||
"Remediation Log" in SECURITY_FINDINGS.md: finding ID → commit-style summary
|
||||
of what changed.
|
||||
For each **Critical** and **High** finding, draft a minimal, targeted fix.
|
||||
Do **not** edit `legacy/` — write all fixes as a single unified diff to
|
||||
`analysis/$1/security_remediation.patch`, with a comment line above each
|
||||
hunk citing the finding ID it addresses (`# SEC-001: parameterize the query`).
|
||||
|
||||
Show the cumulative diff:
|
||||
```bash
|
||||
git -C legacy/$1 diff
|
||||
```
|
||||
Add a **Remediation Log** section to SECURITY_FINDINGS.md mapping each
|
||||
finding ID → one-line summary of the proposed fix and the patch hunk that
|
||||
implements it.
|
||||
|
||||
## Verify
|
||||
|
||||
Re-run the security-auditor against the patched code to confirm the
|
||||
Critical/High findings are resolved. Update the scorecard with before/after.
|
||||
Spawn the **security-auditor** again to **review the patch** against the
|
||||
original code:
|
||||
|
||||
"Review analysis/$1/security_remediation.patch against legacy/$1. For each
|
||||
hunk: does it fully remediate the cited finding? Does it introduce new
|
||||
vulnerabilities or change behavior beyond the fix? Return one verdict per
|
||||
hunk: RESOLVES / PARTIAL / INTRODUCES-RISK, with a one-line reason."
|
||||
|
||||
Add a **Patch Review** section to SECURITY_FINDINGS.md with the verdicts.
|
||||
If any hunk is PARTIAL or INTRODUCES-RISK, revise the patch and re-review.
|
||||
|
||||
## Present
|
||||
|
||||
Tell the user the artifacts are ready:
|
||||
- `analysis/$1/SECURITY_FINDINGS.md` — findings, remediation log, patch review
|
||||
- `analysis/$1/security_remediation.patch` — review, then apply if appropriate
|
||||
with `git -C legacy/$1 apply ../../analysis/$1/security_remediation.patch`
|
||||
- Re-run `/modernize-harden $1` after applying to confirm resolution
|
||||
|
||||
Suggest: `glow -p analysis/$1/SECURITY_FINDINGS.md`
|
||||
|
||||
@ -11,39 +11,44 @@ connect? This is the map an engineer needs before touching anything.
|
||||
## What to produce
|
||||
|
||||
Write a one-off analysis script (Python or shell — your choice) that parses
|
||||
the source under `legacy/$1` and extracts the four datasets below. Cover
|
||||
the parse targets that are real for the stack you're looking at — these are
|
||||
the ones LLMs reliably miss:
|
||||
the source under `legacy/$1` and extracts the four datasets below. Three
|
||||
principles apply across stacks; getting them wrong produces a misleading map:
|
||||
|
||||
- **Program/module call graph** — who calls whom.
|
||||
- COBOL/CICS: `CALL '...'` and `EXEC CICS LINK/XCTL PROGRAM(...)`. Most
|
||||
`PROGRAM(...)` targets are **data-names, not literals** — resolve them
|
||||
against working-storage `VALUE` clauses and any menu/route copybooks
|
||||
before declaring an edge unresolvable.
|
||||
- Java: class-level imports/invocations. Node: `require`/`import`.
|
||||
- **Data dependency graph** — which programs read/write which data stores.
|
||||
- COBOL batch: `SELECT ... ASSIGN TO <ddname>` joined with JCL `DD`
|
||||
statements (this is the *only* way to attribute file I/O to a program).
|
||||
- COBOL/CICS online: `EXEC CICS READ/WRITE/REWRITE/DELETE/STARTBR/READNEXT/
|
||||
READPREV ... FILE(...)` joined with `DEFINE FILE` in the CSD.
|
||||
- DB2: `EXEC SQL ... END-EXEC` table references — *not* JCL DD; DB2 access
|
||||
is via plan/package binds.
|
||||
- BMS: `SEND MAP`/`RECEIVE MAP` ↔ map source under `bms/` and copybooks
|
||||
under `cpy-bms/` (or wherever the maps live).
|
||||
- Java: JPA/MyBatis entities & tables. Node: model files.
|
||||
- **Entry points** — whatever the stack's outermost invokers are. Mainframe:
|
||||
JCL `EXEC PGM=` steps **and** CICS `DEFINE TRANSACTION ... PROGRAM(...)`
|
||||
from the CSD — without the CSD, every online program looks unreachable.
|
||||
Web: HTTP routes. CLI: argv parsing.
|
||||
- **Dead-end candidates** — modules with no inbound edges. **Only trust this
|
||||
once the entry-point and call-edge types above are all in the graph**, and
|
||||
suppress the dead claim for any module that could be the target of an
|
||||
unresolved dynamic call. A naive grep-only graph will mark most CICS
|
||||
programs dead.
|
||||
1. **Edges live in two places** — direct calls in source, *and* dispatcher/
|
||||
router calls whose targets are variables (config tables, route maps,
|
||||
dependency injection, dynamic dispatch). Resolve variables against config
|
||||
before declaring an edge unresolvable.
|
||||
2. **The code↔storage join is usually external configuration**, not source —
|
||||
job/deployment descriptors map logical names to physical stores.
|
||||
3. **Entry points usually live in deployment config**, not source — without
|
||||
parsing it, every top-level module looks unreachable.
|
||||
|
||||
For COBOL fixed-format, slice columns 8-72 and skip `*` indicator lines
|
||||
(column 7) before regex matching, or you'll match sequence numbers and
|
||||
commented-out code.
|
||||
Extract:
|
||||
|
||||
- **Program/module call graph** — direct calls (`CALL`, method invocations,
|
||||
`import`/`require`) *and* dispatcher calls (`EXEC CICS LINK/XCTL`, DI
|
||||
container wiring, framework routing, reflection/factory). Resolve variable
|
||||
call targets against route tables, copybooks, config, or constant pools.
|
||||
- **Data dependency graph** — which modules read/write which data stores,
|
||||
joined through the relevant config: `SELECT…ASSIGN TO` ↔ JCL `DD` (batch
|
||||
COBOL), `EXEC CICS READ/WRITE…FILE()` ↔ CSD `DEFINE FILE` (CICS online),
|
||||
`EXEC SQL` table refs (embedded SQL), ORM annotations/mappings (Java/.NET),
|
||||
model files (Node/Python/Ruby). Include UI/screen bindings (BMS maps, JSPs,
|
||||
templates) — they're dependencies too.
|
||||
- **Entry points** — whatever the stack's outermost invoker is, read from
|
||||
where it's defined: JCL `EXEC PGM=` and CICS CSD `DEFINE TRANSACTION`
|
||||
(mainframe), `web.xml`/route annotations/route files (web), `main()`/argv
|
||||
parsing (CLI), queue/scheduler subscriptions (event-driven).
|
||||
- **Dead-end candidates** — modules with no inbound edges. **Only meaningful
|
||||
once all the entry-point and call-edge types above are in the graph.**
|
||||
Suppress the dead claim for anything that could be the target of an
|
||||
unresolved dynamic call. A grep-only graph will mark most dispatcher-driven
|
||||
modules (CICS programs, Spring controllers, ORM-bound DAOs) dead when they
|
||||
aren't.
|
||||
|
||||
If the source is fixed-column (COBOL columns 8–72, RPG, etc.), slice the
|
||||
code area and strip comment lines before regex matching, or you'll match
|
||||
sequence numbers and commented-out code.
|
||||
|
||||
Save the script as `analysis/$1/extract_topology.py` (or `.sh`) so it can be
|
||||
re-run and audited. Have it write a machine-readable
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user