coding-agent-skills 0.2.9 → 0.2.11

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.
Files changed (69) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +6 -0
  3. package/ROADMAP.md +20 -15
  4. package/bin/coding-agent-skills +14 -0
  5. package/docs/adapters/README.md +36 -0
  6. package/docs/adapters/project-installation.md +23 -0
  7. package/docs/adapters/real-project-adoption.md +2 -1
  8. package/docs/architecture/README.md +5 -3
  9. package/docs/release/README.md +4 -2
  10. package/docs/release/npm-package.md +10 -3
  11. package/docs/safety/README.md +10 -1
  12. package/docs/testing/README.md +15 -0
  13. package/docs/usage/README.md +24 -5
  14. package/examples/command-policies/env-audit.json +73 -0
  15. package/examples/command-policies/secret-audit.json +71 -0
  16. package/examples/evidence-packs/env-audit.json +55 -0
  17. package/examples/evidence-packs/secret-audit.json +55 -0
  18. package/examples/manifests/env-audit.json +14 -0
  19. package/examples/manifests/secret-audit.json +14 -0
  20. package/examples/workflows/env-audit.md +16 -0
  21. package/examples/workflows/secret-audit.md +10 -0
  22. package/package.json +3 -1
  23. package/runs/skill-runs.md +26 -0
  24. package/schemas/project-adapter-installation.schema.json +4 -0
  25. package/schemas/project-adapter.schema.json +4 -0
  26. package/scripts/lib/env-audit.mjs +640 -0
  27. package/scripts/lib/pack-rules.mjs +20 -2
  28. package/scripts/lib/secret-audit.mjs +510 -0
  29. package/scripts/render-env-audit.mjs +8 -0
  30. package/scripts/render-secret-audit.mjs +8 -0
  31. package/scripts/test-pack.mjs +139 -1
  32. package/scripts/validate-pack.mjs +8 -2
  33. package/skills/env-audit/SKILL.md +58 -0
  34. package/skills/env-audit/adapter-interface.md +12 -0
  35. package/skills/env-audit/agents/openai.yaml +4 -0
  36. package/skills/env-audit/checklist.md +7 -0
  37. package/skills/env-audit/evidence-template.md +17 -0
  38. package/skills/env-audit/examples.md +28 -0
  39. package/skills/env-audit/failure-modes.md +5 -0
  40. package/skills/secret-audit/SKILL.md +57 -0
  41. package/skills/secret-audit/adapter-interface.md +12 -0
  42. package/skills/secret-audit/agents/openai.yaml +4 -0
  43. package/skills/secret-audit/checklist.md +7 -0
  44. package/skills/secret-audit/evidence-template.md +15 -0
  45. package/skills/secret-audit/examples.md +27 -0
  46. package/skills/secret-audit/failure-modes.md +5 -0
  47. package/tests/fixtures/env-audit/adapter-project/.coding-agent/adapters/env-audit-fixture/adapter.json +56 -0
  48. package/tests/fixtures/env-audit/adapter-project/.coding-agent/skills.json +23 -0
  49. package/tests/fixtures/env-audit/adapter-project/README.md +3 -0
  50. package/tests/fixtures/env-audit/adapter-project/package.json +4 -0
  51. package/tests/fixtures/env-audit/adapter-project/src/config.ts +2 -0
  52. package/tests/fixtures/env-audit/static-project/.env.example +3 -0
  53. package/tests/fixtures/env-audit/static-project/README.md +3 -0
  54. package/tests/fixtures/env-audit/static-project/docs/setup.md +3 -0
  55. package/tests/fixtures/env-audit/static-project/package.json +4 -0
  56. package/tests/fixtures/env-audit/static-project/src/config.ts +4 -0
  57. package/tests/fixtures/env-audit/static-project/src/deno.ts +1 -0
  58. package/tests/fixtures/secret-audit/adapter-project/.coding-agent/adapters/secret-audit-fixture/adapter.json +53 -0
  59. package/tests/fixtures/secret-audit/adapter-project/.coding-agent/skills.json +23 -0
  60. package/tests/fixtures/secret-audit/adapter-project/README.md +3 -0
  61. package/tests/fixtures/secret-audit/adapter-project/package.json +4 -0
  62. package/tests/fixtures/secret-audit/adapter-project/src/placeholder.ts +1 -0
  63. package/tests/fixtures/secret-audit/static-project/.env.example +1 -0
  64. package/tests/fixtures/secret-audit/static-project/README.md +3 -0
  65. package/tests/fixtures/secret-audit/static-project/package.json +4 -0
  66. package/tests/fixtures/secret-audit/static-project/src/config.ts +1 -0
  67. package/tests/fixtures/triggers/cases.json +25 -1
  68. package/tests/trigger/README.md +4 -0
  69. package/work-ledger.md +36 -11
@@ -47,6 +47,16 @@ import {
47
47
  renderRouteTraceReport,
48
48
  routeTraceCliResult,
49
49
  } from "./lib/route-trace.mjs";
50
+ import {
51
+ buildEnvAuditReport,
52
+ envAuditCliResult,
53
+ renderEnvAuditReport,
54
+ } from "./lib/env-audit.mjs";
55
+ import {
56
+ buildSecretAuditReport,
57
+ renderSecretAuditReport,
58
+ secretAuditCliResult,
59
+ } from "./lib/secret-audit.mjs";
50
60
  import {
51
61
  adapterUpgradeCliResult,
52
62
  checkAdapterUpgrade,
@@ -262,6 +272,8 @@ test("local CLI maps approved commands to existing safe scripts", () => {
262
272
  assert.ok(cliText.includes("scripts/validate-project-adapters.mjs"));
263
273
  assert.ok(cliText.includes("scripts/render-adapter-repo-map.mjs"));
264
274
  assert.ok(cliText.includes("scripts/render-route-trace.mjs"));
275
+ assert.ok(cliText.includes("scripts/render-env-audit.mjs"));
276
+ assert.ok(cliText.includes("scripts/render-secret-audit.mjs"));
265
277
  assert.ok(cliText.includes("scripts/validate-adapters.mjs"));
266
278
  assert.ok(!cliText.includes(".env"));
267
279
 
@@ -287,6 +299,14 @@ test("local CLI maps approved commands to existing safe scripts", () => {
287
299
  ["route-trace", path.join(fixtureRoot, "route-trace", "static-project")],
288
300
  /# Route Trace Report/,
289
301
  ],
302
+ [
303
+ ["env-audit", path.join(fixtureRoot, "env-audit", "static-project")],
304
+ /# Env Audit Report/,
305
+ ],
306
+ [
307
+ ["secret-audit", path.join(fixtureRoot, "secret-audit", "static-project")],
308
+ /# Secret Audit Report/,
309
+ ],
290
310
  ];
291
311
 
292
312
  for (const [args, expected] of commands) {
@@ -311,7 +331,7 @@ test("local CLI maps approved commands to existing safe scripts", () => {
311
331
  test("npm package metadata is public-ready and dependency-free", () => {
312
332
  const packageJson = readJson("package.json");
313
333
  assert.equal(packageJson.name, "coding-agent-skills");
314
- assert.equal(packageJson.version, "0.2.9");
334
+ assert.equal(packageJson.version, "0.2.11");
315
335
  assert.equal(
316
336
  packageJson.description,
317
337
  "Evidence-first, read-only coding-agent skills and project adapter tooling.",
@@ -324,6 +344,8 @@ test("npm package metadata is public-ready and dependency-free", () => {
324
344
  "agent-skills",
325
345
  "repo-map",
326
346
  "route-trace",
347
+ "env-audit",
348
+ "secret-audit",
327
349
  "project-adapters",
328
350
  "code-validation",
329
351
  "cli",
@@ -451,6 +473,122 @@ test("route-trace does not broaden a repo-map-only project adapter", () => {
451
473
  assert.match(renderRouteTraceReport(result), /route-trace is not enabled/);
452
474
  });
453
475
 
476
+ test("env-audit identifies variable names without reading .env values", () => {
477
+ const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "env-audit-fixture-"));
478
+ fs.cpSync(path.join(root, "tests", "fixtures", "env-audit", "static-project"), temporary, {
479
+ recursive: true,
480
+ });
481
+ fs.writeFileSync(path.join(temporary, ".env"), "SHOULD_NOT_BE_READ=synthetic-fixture-value\n");
482
+
483
+ const result = buildEnvAuditReport(
484
+ temporary,
485
+ { coreRoot: root },
486
+ );
487
+
488
+ assert.equal(result.status, "complete");
489
+ assert.ok(result.filesScanned.includes(".env.example"));
490
+ assert.ok(!result.filesScanned.includes(".env"));
491
+ assert.ok(result.skipped.some((item) => item.path === ".env"));
492
+ const names = result.variables.map((variable) => variable.name);
493
+ assert.ok(names.includes("DATABASE_URL"));
494
+ assert.ok(names.includes("NEXT_PUBLIC_APP_URL"));
495
+ assert.ok(names.includes("PORT"));
496
+ assert.ok(names.includes("SERVICE_TOKEN"));
497
+ assert.ok(names.includes("DENO_REGION"));
498
+ const rendered = renderEnvAuditReport(result);
499
+ assert.match(rendered, /DATABASE_URL/);
500
+ assert.doesNotMatch(rendered, /synthetic-fixture-value/);
501
+ });
502
+
503
+ test("env-audit respects adapter-declared scope", () => {
504
+ const result = buildEnvAuditReport(
505
+ path.join(root, "tests", "fixtures", "env-audit", "adapter-project"),
506
+ { coreRoot: root },
507
+ );
508
+
509
+ assert.equal(result.status, "complete");
510
+ assert.equal(result.adapter.enabled, true);
511
+ assert.deepEqual(result.scopePaths, ["src"]);
512
+ assert.deepEqual(result.filesScanned, ["src/config.ts"]);
513
+ assert.ok(result.variables.some((variable) => variable.name === "ADAPTER_ONLY_VALUE"));
514
+ assert.ok(result.warnings.includes("env-audit used adapter-declared safe read paths only"));
515
+ const cli = envAuditCliResult(
516
+ path.join(root, "tests", "fixtures", "env-audit", "adapter-project"),
517
+ { coreRoot: root },
518
+ );
519
+ assert.equal(cli.exitCode, 0);
520
+ assert.match(cli.lines.join("\n"), /Env-audit enabled: yes/);
521
+ });
522
+
523
+ test("env-audit does not broaden a repo-map-only project adapter", () => {
524
+ const result = buildEnvAuditReport(
525
+ path.join(root, "tests", "fixtures", "project-adapter-installation", "valid-exact-pin"),
526
+ { coreRoot: root },
527
+ );
528
+
529
+ assert.equal(result.status, "partial");
530
+ assert.equal(result.filesScanned.length, 0);
531
+ assert.equal(result.variables.length, 0);
532
+ assert.match(renderEnvAuditReport(result), /env-audit is not enabled/);
533
+ });
534
+
535
+ test("secret-audit reports high-confidence findings without printing values", () => {
536
+ const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "secret-audit-fixture-"));
537
+ fs.cpSync(path.join(root, "tests", "fixtures", "secret-audit", "static-project"), temporary, {
538
+ recursive: true,
539
+ });
540
+ const syntheticSecret = ["github", "_pat_", "A".repeat(24)].join("");
541
+ fs.writeFileSync(
542
+ path.join(temporary, "src", "leak.ts"),
543
+ `export const candidate = "${syntheticSecret}";\n`,
544
+ );
545
+ fs.writeFileSync(path.join(temporary, ".env"), `DO_NOT_READ=${syntheticSecret}\n`);
546
+
547
+ const result = buildSecretAuditReport(temporary, { coreRoot: root });
548
+ const rendered = renderSecretAuditReport(result);
549
+
550
+ assert.equal(result.status, "complete");
551
+ assert.ok(result.filesScanned.includes("src/leak.ts"));
552
+ assert.ok(!result.filesScanned.includes(".env"));
553
+ assert.ok(result.skipped.some((item) => item.path === ".env"));
554
+ assert.ok(result.findings.some((finding) => finding.path === "src/leak.ts"));
555
+ assert.ok(result.findings.some((finding) => finding.type === "github-token"));
556
+ assert.match(rendered, /src\/leak\.ts/);
557
+ assert.match(rendered, /values omitted/);
558
+ assert.doesNotMatch(rendered, new RegExp(syntheticSecret));
559
+ });
560
+
561
+ test("secret-audit respects adapter-declared scope", () => {
562
+ const result = buildSecretAuditReport(
563
+ path.join(root, "tests", "fixtures", "secret-audit", "adapter-project"),
564
+ { coreRoot: root },
565
+ );
566
+
567
+ assert.equal(result.status, "complete");
568
+ assert.equal(result.adapter.enabled, true);
569
+ assert.deepEqual(result.scopePaths, ["src"]);
570
+ assert.deepEqual(result.filesScanned, ["src/placeholder.ts"]);
571
+ assert.ok(result.warnings.includes("secret-audit used adapter-declared safe read paths only"));
572
+ const cli = secretAuditCliResult(
573
+ path.join(root, "tests", "fixtures", "secret-audit", "adapter-project"),
574
+ { coreRoot: root },
575
+ );
576
+ assert.equal(cli.exitCode, 0);
577
+ assert.match(cli.lines.join("\n"), /Secret-audit enabled: yes/);
578
+ });
579
+
580
+ test("secret-audit does not broaden a repo-map-only project adapter", () => {
581
+ const result = buildSecretAuditReport(
582
+ path.join(root, "tests", "fixtures", "project-adapter-installation", "valid-exact-pin"),
583
+ { coreRoot: root },
584
+ );
585
+
586
+ assert.equal(result.status, "partial");
587
+ assert.equal(result.filesScanned.length, 0);
588
+ assert.equal(result.findings.length, 0);
589
+ assert.match(renderSecretAuditReport(result), /secret-audit is not enabled/);
590
+ });
591
+
454
592
  test("validate-pack accepts installed package trees without source-only gitignore", () => {
455
593
  const temporaryRoot = fs.mkdtempSync(path.join(os.tmpdir(), "installed-package-"));
456
594
  const installedRoot = path.join(temporaryRoot, "coding-agent-skills");
@@ -96,12 +96,16 @@ const requiredRootFiles = [
96
96
  "scripts/render-evidence-archive-report.mjs",
97
97
  "scripts/render-adapter-repo-map.mjs",
98
98
  "scripts/render-route-trace.mjs",
99
+ "scripts/render-env-audit.mjs",
100
+ "scripts/render-secret-audit.mjs",
99
101
  "scripts/check-adapter-upgrade.mjs",
100
102
  "scripts/check-adapter-upgrade-chain.mjs",
101
103
  "scripts/validate-adapters.mjs",
102
104
  "scripts/validate-project-adapters.mjs",
103
105
  "scripts/lib/adapter-repo-map.mjs",
104
106
  "scripts/lib/route-trace.mjs",
107
+ "scripts/lib/env-audit.mjs",
108
+ "scripts/lib/secret-audit.mjs",
105
109
  "scripts/lib/adapter-upgrade.mjs",
106
110
  "scripts/lib/adapter-upgrade-chain.mjs",
107
111
  "scripts/lib/adapter-discovery.mjs",
@@ -675,8 +679,8 @@ if (packageJson) {
675
679
  if (packageJson.name !== "coding-agent-skills") {
676
680
  failures.push("package.json has unexpected package name");
677
681
  }
678
- if (packageJson.version !== "0.2.9") {
679
- failures.push("package.json version must be 0.2.9 for public package validation");
682
+ if (packageJson.version !== "0.2.11") {
683
+ failures.push("package.json version must be 0.2.11 for public package validation");
680
684
  }
681
685
  if (packageJson.type !== "module") failures.push("package.json must preserve ESM mode");
682
686
  if (packageJson.private !== false) {
@@ -695,6 +699,8 @@ if (packageJson) {
695
699
  "agent-skills",
696
700
  "repo-map",
697
701
  "route-trace",
702
+ "env-audit",
703
+ "secret-audit",
698
704
  "project-adapters",
699
705
  "code-validation",
700
706
  "cli",
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: env-audit
3
+ description: Identify environment variable names and configuration requirements from static files without reading .env files or printing values. Use when Codex must map required, optional, sample, or inferred environment names before implementation, deployment planning, or handoff; do not use for secret validation, credential testing, API calls, runtime checks, builds, tests, deployments, migrations, or secret-file reads.
4
+ ---
5
+
6
+ # Env Audit
7
+
8
+ Identify environment variable names from bounded static evidence and emit a value-free report. Remain audit-only and fail closed when evidence would require secret files, runtime state, or credential validation.
9
+
10
+ This skill must not change project files, Git state, dependencies, runtime state, services,
11
+ databases, remotes, or deployment state.
12
+
13
+ ## Purpose And Use
14
+
15
+ Use this skill to map statically visible environment variable names, sample declarations, and configuration references before changing code, documenting setup, or preparing handoff. It can classify names as sample, required, optional, or inferred, but it must not claim that any value exists or works.
16
+
17
+ Do not use this skill for secret auditing, credential validation, live service checks, runtime truth claims, deployment readiness, migrations, builds, tests, or package installation.
18
+
19
+ ## Inputs
20
+
21
+ Require a project root or starting path. Optionally accept a project adapter, intended config area, maximum static scan depth, or named framework/config family to prioritize.
22
+
23
+ Do not assume `.env` files may be read, variable values are safe, documented names are complete, sample files are current, runtime-injected variables are visible, or an adapter covers every configuration surface.
24
+
25
+ ## Procedure
26
+
27
+ 1. Record user intent, project root, declared scope, adapter state, and safety boundary.
28
+ 2. Validate a project adapter when present before reading adapter-declared metadata.
29
+ 3. If an adapter is present but does not enable `env-audit`, stop static file reading and report the adapter-limited skip.
30
+ 4. Build the scan scope from adapter safe read paths when available; otherwise use a bounded generic static scan.
31
+ 5. Exclude `.env`, `.env.*` except `.env.example`, secret-bearing paths, generated paths, dependency paths, and oversized files before reading.
32
+ 6. Extract environment variable names from safe static patterns such as `process.env.NAME`, `import.meta.env.NAME`, `Deno.env.get("NAME")`, `env("NAME")`, docs, and `.env.example` declarations.
33
+ 7. Never print values, line contents, tokens, credentials, or raw secret-like matches.
34
+ 8. Label every finding as sample, required, optional, inferred, skipped, or not verified.
35
+ 9. Report skipped files, unverified runtime/secret-store areas, branch state warnings, and safety refusals.
36
+ 10. Emit the shared evidence pack or env-audit report before claiming completion.
37
+
38
+ Use [checklist.md](checklist.md). Consult [failure-modes.md](failure-modes.md), [adapter-interface.md](adapter-interface.md), and [examples.md](examples.md). Format findings with [evidence-template.md](evidence-template.md).
39
+
40
+ ## Evidence, Recovery, And Dependencies
41
+
42
+ Emit repository identity, adapter state, scan scope, ignored paths, variable names, classifications, file references, sample files inspected, skipped items, not-verified areas, warnings, and changed-state declaration through the shared evidence-pack contract.
43
+
44
+ Recover from missing adapters, unreadable files, ambiguous variable names, or secret-bearing paths by narrowing scope and reporting uncertainty. Never recover by reading `.env`, printing values, validating credentials, contacting APIs, installing dependencies, running builds/tests, broadening adapter scope, or mutating files.
45
+
46
+ This skill depends on the evidence-pack contract and may consume validated project adapters. Adapters may add safe paths, ignored paths, documentation precedence, and evidence requirements, but cannot weaken policy or turn this skill into credential validation.
47
+
48
+ ## Approval Boundary
49
+
50
+ Explicit approval may permit one named non-secret static file read outside normal config paths. Approval does not permit `.env` or secret-file reads, value printing, credential validation, API calls, builds, tests, package installation, runtime checks, deployments, migrations, Git mutation, or project writes.
51
+
52
+ ## Completion
53
+
54
+ Claim `complete` only when the declared static scan scope was inspected, variable names are reported without values, skipped and not-verified areas are recorded with consequences, adapter limitations are explicit, and no project, Git, dependency, runtime, service, or remote state changed.
55
+
56
+ Report `partial`, `failed`, or `blocked` when adapter scope prevents env scanning, requested evidence requires secret files or runtime state, the project root cannot be established, or safety exclusions prevent a requested conclusion. Never claim credential presence or validity from static findings.
57
+
58
+ These conditions are both the acceptance criteria and definition of done.
@@ -0,0 +1,12 @@
1
+ Adapters may enable `env-audit` by declaring the skill ID with unchanged `audit-only`
2
+ mode and compatible version `0.2.3` or `0.2.x`.
3
+
4
+ Useful extension fields:
5
+
6
+ - `safeReadPaths`: source, docs, sample, and config paths that may contain env names.
7
+ - `ignoredPaths`: generated, dependency, runtime-output, and secret-bearing paths to skip.
8
+ - `documentationPrecedence`: docs that may explain required or optional env names.
9
+ - `requiredEvidence`: evidence the report must include before completion.
10
+
11
+ Adapters must not add `.env`, `.env.*` except `.env.example`, credentials, secret stores,
12
+ runtime checks, API calls, builds, tests, deployments, migrations, or project writes.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Env Audit"
3
+ short_description: "Map env variable names without reading values"
4
+ default_prompt: "Audit the statically visible environment variable names in this repository without changing project state. Do not read .env files or print values."
@@ -0,0 +1,7 @@
1
+ - Confirm project root, branch state, and adapter state.
2
+ - Validate adapter before consuming any adapter-declared paths.
3
+ - Refuse `.env`, `.env.*` except `.env.example`, secret-bearing paths, and generated outputs.
4
+ - Scan only bounded static source, docs, sample, and config files.
5
+ - Record variable names, classifications, and file references without values.
6
+ - Record skipped files and runtime/secret-store areas that were not verified.
7
+ - Confirm no files, dependencies, runtime state, services, remotes, or databases changed.
@@ -0,0 +1,17 @@
1
+ ## Env Audit Evidence
2
+
3
+ - Repository root:
4
+ - Branch state:
5
+ - Adapter state:
6
+ - Scan scope:
7
+ - Ignored paths:
8
+ - Static files scanned:
9
+ - Sample files inspected:
10
+ - Variable names found:
11
+ - Required names:
12
+ - Optional names:
13
+ - Inferred names:
14
+ - Skipped items:
15
+ - Not verified:
16
+ - Safety refusals:
17
+ - Changed state: none
@@ -0,0 +1,28 @@
1
+ ## Safe
2
+
3
+ ```bash
4
+ coding-agent-skills env-audit /workspace/app
5
+ ```
6
+
7
+ Produces a value-free list of names such as `DATABASE_URL`, `NEXT_PUBLIC_API_URL`, and
8
+ `PORT`, with file references and classifications.
9
+
10
+ ```bash
11
+ node scripts/render-env-audit.mjs tests/fixtures/env-audit/static-project
12
+ ```
13
+
14
+ Runs the synthetic fixture scanner without reading `.env` files or contacting services.
15
+
16
+ ## Unsafe
17
+
18
+ ```bash
19
+ cat .env
20
+ ```
21
+
22
+ Secret-file reads are forbidden.
23
+
24
+ ```bash
25
+ npm run dev
26
+ ```
27
+
28
+ Runtime checks are outside this skill.
@@ -0,0 +1,5 @@
1
+ - **Adapter not enabled:** report `partial` and do not broaden target-project scanning.
2
+ - **Secret-bearing path requested:** skip the file and record the safety exclusion.
3
+ - **Dynamic variable names:** report as not verified instead of guessing.
4
+ - **Large or unreadable files:** skip with consequence and continue bounded scanning.
5
+ - **Credential validation requested:** refuse and explain that only names are in scope.
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: secret-audit
3
+ description: Find high-confidence secret exposure risks in static tracked files without printing matched values. Use when Codex must identify possible token, key, credential, or private-key exposure by file path and count before handoff or cleanup; do not use for reading .env files, credential stores, rotation, validation, API calls, builds, tests, deployments, migrations, or mutation.
4
+ ---
5
+
6
+ # Secret Audit
7
+
8
+ Identify high-confidence secret-like patterns from bounded static evidence and emit a redacted report. Remain audit-only and fail closed when evidence would require reading secret files or printing values.
9
+
10
+ This skill must not change project files, Git state, dependencies, runtime state, services,
11
+ databases, remotes, or deployment state.
12
+
13
+ ## Purpose And Use
14
+
15
+ Use this skill to find possible tracked secret exposure by file path, pattern type, and count before handoff, publication, or cleanup. It can report suspicious files and categories, but it must not print matched values or claim whether a credential is active.
16
+
17
+ Do not use this skill for credential validation, token rotation, secret-store inspection, runtime truth claims, deployment readiness, migrations, builds, tests, or package installation.
18
+
19
+ ## Inputs
20
+
21
+ Require a project root or starting path. Optionally accept a project adapter, intended scan area, maximum static scan depth, or known synthetic fixture allowance.
22
+
23
+ Do not assume ignored secret files may be read, high-confidence patterns prove exploitability, absence of findings proves absence of secrets, package contents match Git contents, or a project adapter covers every exposure surface.
24
+
25
+ ## Procedure
26
+
27
+ 1. Record user intent, project root, declared scope, adapter state, and safety boundary.
28
+ 2. Validate a project adapter when present before reading adapter-declared metadata.
29
+ 3. If an adapter is present but does not enable `secret-audit`, stop static file reading and report the adapter-limited skip.
30
+ 4. Build scan scope from adapter safe read paths when available; otherwise use a bounded generic static scan.
31
+ 5. Exclude `.env`, `.env.*` except deliberate `.env.example`, secret-bearing paths, generated paths, dependency paths, and oversized files before reading.
32
+ 6. Scan safe static text files for high-confidence secret-like shapes.
33
+ 7. Report only file path, finding type, and count. Never print matched values, snippets, tokens, credentials, or raw secret-like content.
34
+ 8. Label findings, skipped items, not-verified areas, warnings, and safety refusals.
35
+ 9. Emit the shared evidence pack or secret-audit report before claiming completion.
36
+
37
+ Use [checklist.md](checklist.md). Consult [failure-modes.md](failure-modes.md), [adapter-interface.md](adapter-interface.md), and [examples.md](examples.md). Format findings with [evidence-template.md](evidence-template.md).
38
+
39
+ ## Evidence, Recovery, And Dependencies
40
+
41
+ Emit repository identity, adapter state, scan scope, ignored paths, files scanned, finding path/type/count, skipped items, not-verified areas, warnings, and changed-state declaration through the shared evidence-pack contract.
42
+
43
+ Recover from missing adapters, unreadable files, ambiguous patterns, or secret-bearing paths by narrowing scope and reporting uncertainty. Never recover by reading `.env`, printing values, validating credentials, rotating tokens, contacting APIs, installing dependencies, running builds/tests, broadening adapter scope, or mutating files.
44
+
45
+ This skill depends on the evidence-pack contract and may consume validated project adapters. Adapters may add safe paths, ignored paths, documentation precedence, and evidence requirements, but cannot weaken policy or turn this skill into credential handling.
46
+
47
+ ## Approval Boundary
48
+
49
+ Explicit approval may permit one named non-secret static file read outside normal source paths. Approval does not permit `.env` or secret-file reads, value printing, credential validation, token rotation, API calls, builds, tests, package installation, runtime checks, deployments, migrations, Git mutation, or project writes.
50
+
51
+ ## Completion
52
+
53
+ Claim `complete` only when the declared static scan scope was inspected, all findings are path/type/count only, skipped and not-verified areas are recorded with consequences, adapter limitations are explicit, and no project, Git, dependency, runtime, service, or remote state changed.
54
+
55
+ Report `partial`, `failed`, or `blocked` when adapter scope prevents scanning, requested evidence requires secret files or credential stores, the project root cannot be established, or safety exclusions prevent a requested conclusion. Never claim credential validity, revocation, or full absence of secrets from static findings alone.
56
+
57
+ These conditions are both the acceptance criteria and definition of done.
@@ -0,0 +1,12 @@
1
+ Adapters may enable `secret-audit` by declaring the skill ID with unchanged `audit-only`
2
+ mode and compatible version `0.2.3` or `0.2.x`.
3
+
4
+ Useful extension fields:
5
+
6
+ - `safeReadPaths`: source, docs, sample, and config paths safe for static pattern scanning.
7
+ - `ignoredPaths`: generated, dependency, runtime-output, and secret-bearing paths to skip.
8
+ - `documentationPrecedence`: docs that explain known synthetic fixtures or report policy.
9
+ - `requiredEvidence`: evidence the report must include before completion.
10
+
11
+ Adapters must not add `.env`, credentials, secret stores, credential API calls, rotation,
12
+ builds, tests, deployments, migrations, or project writes.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Secret Audit"
3
+ short_description: "Find secret exposure risks without printing values"
4
+ default_prompt: "Audit high-confidence secret exposure risks in this repository without changing project state. Do not read .env files, print matched values, or rotate credentials."
@@ -0,0 +1,7 @@
1
+ - Confirm project root, branch state, and adapter state.
2
+ - Validate adapter before consuming any adapter-declared paths.
3
+ - Refuse `.env`, `.env.*` except `.env.example`, secret-bearing paths, and generated outputs.
4
+ - Scan only bounded static text files.
5
+ - Record file path, finding type, and count only.
6
+ - Record skipped files and secret stores/history that were not verified.
7
+ - Confirm no files, dependencies, runtime state, services, remotes, or databases changed.
@@ -0,0 +1,15 @@
1
+ ## Secret Audit Evidence
2
+
3
+ - Repository root:
4
+ - Branch state:
5
+ - Adapter state:
6
+ - Scan scope:
7
+ - Ignored paths:
8
+ - Static files scanned:
9
+ - Finding paths:
10
+ - Finding types:
11
+ - Finding counts:
12
+ - Skipped items:
13
+ - Not verified:
14
+ - Safety refusals:
15
+ - Changed state: none
@@ -0,0 +1,27 @@
1
+ ## Safe
2
+
3
+ ```bash
4
+ coding-agent-skills secret-audit /workspace/app
5
+ ```
6
+
7
+ Reports possible secret exposure by path, type, and count only.
8
+
9
+ ```bash
10
+ node scripts/render-secret-audit.mjs tests/fixtures/secret-audit/static-project
11
+ ```
12
+
13
+ Runs the synthetic fixture scanner without reading `.env` files or printing matches.
14
+
15
+ ## Unsafe
16
+
17
+ ```bash
18
+ cat .env
19
+ ```
20
+
21
+ Secret-file reads are forbidden.
22
+
23
+ ```bash
24
+ gh secret list
25
+ ```
26
+
27
+ Credential-store and API inspection are outside this skill.
@@ -0,0 +1,5 @@
1
+ - **Adapter not enabled:** report `partial` and do not broaden target-project scanning.
2
+ - **Secret-bearing path requested:** skip the file and record the safety exclusion.
3
+ - **Synthetic test token needed:** generate it in a temporary test directory, never package it.
4
+ - **Credential validation requested:** refuse and explain that only static path/count evidence is in scope.
5
+ - **No findings:** report that no high-confidence matches were found in scanned files, not that the repo is secret-free.
@@ -0,0 +1,56 @@
1
+ {
2
+ "adapterId": "env-audit-fixture",
3
+ "adapterVersion": "1.0.0",
4
+ "project": {
5
+ "id": "env-audit-fixture",
6
+ "detection": {
7
+ "rootMarkers": [
8
+ {"kind": "file", "path": "package.json"},
9
+ {"kind": "file", "path": "README.md"}
10
+ ],
11
+ "maximumDepth": 1,
12
+ "scope": "declared-project-root",
13
+ "requireApprovalOutsideScope": true
14
+ }
15
+ },
16
+ "supportedSkills": [
17
+ {
18
+ "id": "env-audit",
19
+ "compatibleVersions": ["0.2.3", "0.2.x"],
20
+ "declaredMode": "audit-only"
21
+ }
22
+ ],
23
+ "extensions": {
24
+ "safeReadPaths": ["src"],
25
+ "ignoredPaths": ["dist", "build"],
26
+ "documentationPrecedence": ["README.md"],
27
+ "commandAliases": [],
28
+ "safeStatusCommands": [],
29
+ "requiredEvidence": ["project root", "adapter scope", "env names", "skipped secret paths"],
30
+ "expectedRuntimeManagers": [],
31
+ "expectedPackageManagers": ["npm"]
32
+ },
33
+ "approvalRequirements": [],
34
+ "inheritance": {
35
+ "sharedRestrictions": "required",
36
+ "deniedOperationCategories": [
37
+ "file-write",
38
+ "package-install",
39
+ "deployment",
40
+ "git-mutation",
41
+ "unrestricted-scan",
42
+ "secret-read",
43
+ "process-mutation",
44
+ "service-mutation",
45
+ "migration-apply",
46
+ "privileged-api"
47
+ ],
48
+ "allowRestrictionRemoval": false,
49
+ "allowModeOverride": false,
50
+ "allowFailureSuppression": false,
51
+ "allowCompletionOverride": false,
52
+ "allowSecretExposure": false,
53
+ "allowRequiredEvidenceRemoval": false,
54
+ "allowScopeExpansionWithoutApproval": false
55
+ }
56
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "declarationVersion": "1.0.0",
3
+ "projectId": "env-audit-fixture",
4
+ "adapterRoot": ".coding-agent/adapters",
5
+ "adapterSchemaVersion": "1.0.0",
6
+ "core": {
7
+ "id": "coding-agent-skills",
8
+ "expectedVersion": "0.2.3",
9
+ "versionPin": ">=0.2.3 <0.3.0"
10
+ },
11
+ "compatibleSkillIds": ["env-audit"],
12
+ "adapters": [
13
+ {
14
+ "id": "env-audit-fixture",
15
+ "version": "1.0.0",
16
+ "skillIds": ["env-audit"]
17
+ }
18
+ ],
19
+ "validationCommand": "node <shared-core>/scripts/validate-project-adapters.mjs <project-root>",
20
+ "evidenceOutput": "validation-output/project-adapters.json",
21
+ "approvalPolicyReference": "docs/coding-agent-approval-policy.md",
22
+ "noSecrets": true
23
+ }
@@ -0,0 +1,3 @@
1
+ # Env Audit Adapter Fixture
2
+
3
+ This fixture narrows env scanning to `src`.
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "fixture-env-audit-adapter",
3
+ "type": "module"
4
+ }
@@ -0,0 +1,2 @@
1
+ export const adapterScoped = process.env.ADAPTER_ONLY_VALUE;
2
+ export const adapterOptional = process.env.ADAPTER_OPTIONAL_VALUE ?? "fallback";
@@ -0,0 +1,3 @@
1
+ DATABASE_URL=
2
+ NEXT_PUBLIC_APP_URL=
3
+ OPTIONAL_FEATURE_FLAG=
@@ -0,0 +1,3 @@
1
+ # Env Audit Static Fixture
2
+
3
+ Requires DATABASE_URL and optional NEXT_PUBLIC_APP_URL. Workers may use QUEUE_NAME.
@@ -0,0 +1,3 @@
1
+ # Setup
2
+
3
+ Set DATABASE_URL before starting locally. NEXT_PUBLIC_APP_URL is optional.
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "fixture-env-audit-static",
3
+ "type": "module"
4
+ }
@@ -0,0 +1,4 @@
1
+ export const databaseUrl = process.env.DATABASE_URL;
2
+ export const port = process.env.PORT ?? "3000";
3
+ export const publicUrl = import.meta.env.NEXT_PUBLIC_APP_URL;
4
+ export const requiredToken = env("SERVICE_TOKEN");
@@ -0,0 +1 @@
1
+ export const denoValue = Deno.env.get("DENO_REGION");