project-shield 1.1.5 → 2.0.0

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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +194 -4
  3. package/dist/auditor/checks/environment.d.ts +7 -0
  4. package/dist/auditor/checks/environment.d.ts.map +1 -0
  5. package/dist/auditor/checks/environment.js +463 -0
  6. package/dist/auditor/checks/environment.js.map +1 -0
  7. package/dist/auditor/checks/hooks.d.ts +13 -0
  8. package/dist/auditor/checks/hooks.d.ts.map +1 -0
  9. package/dist/auditor/checks/hooks.js +234 -0
  10. package/dist/auditor/checks/hooks.js.map +1 -0
  11. package/dist/auditor/engine.d.ts +7 -0
  12. package/dist/auditor/engine.d.ts.map +1 -0
  13. package/dist/auditor/engine.js +183 -0
  14. package/dist/auditor/engine.js.map +1 -0
  15. package/dist/auditor/providers/claude-code.d.ts +17 -0
  16. package/dist/auditor/providers/claude-code.d.ts.map +1 -0
  17. package/dist/auditor/providers/claude-code.js +176 -0
  18. package/dist/auditor/providers/claude-code.js.map +1 -0
  19. package/dist/auditor/providers/types.d.ts +36 -0
  20. package/dist/auditor/providers/types.d.ts.map +1 -0
  21. package/dist/auditor/providers/types.js +4 -0
  22. package/dist/auditor/providers/types.js.map +1 -0
  23. package/dist/index.js +99 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/license/gate.d.ts +3 -0
  26. package/dist/license/gate.d.ts.map +1 -1
  27. package/dist/license/gate.js +9 -0
  28. package/dist/license/gate.js.map +1 -1
  29. package/dist/license/index.d.ts +1 -1
  30. package/dist/license/index.d.ts.map +1 -1
  31. package/dist/license/index.js +3 -1
  32. package/dist/license/index.js.map +1 -1
  33. package/dist/license/storage.d.ts.map +1 -1
  34. package/dist/license/storage.js +5 -0
  35. package/dist/license/storage.js.map +1 -1
  36. package/dist/license/types.d.ts +5 -0
  37. package/dist/license/types.d.ts.map +1 -1
  38. package/dist/license/usage.d.ts +12 -0
  39. package/dist/license/usage.d.ts.map +1 -1
  40. package/dist/license/usage.js +47 -2
  41. package/dist/license/usage.js.map +1 -1
  42. package/dist/output/audit-evidence.d.ts +10 -0
  43. package/dist/output/audit-evidence.d.ts.map +1 -0
  44. package/dist/output/audit-evidence.js +82 -0
  45. package/dist/output/audit-evidence.js.map +1 -0
  46. package/dist/output/audit-fixit.d.ts +34 -0
  47. package/dist/output/audit-fixit.d.ts.map +1 -0
  48. package/dist/output/audit-fixit.js +267 -0
  49. package/dist/output/audit-fixit.js.map +1 -0
  50. package/dist/output/audit-terminal.d.ts +15 -0
  51. package/dist/output/audit-terminal.d.ts.map +1 -0
  52. package/dist/output/audit-terminal.js +200 -0
  53. package/dist/output/audit-terminal.js.map +1 -0
  54. package/dist/retention/expiry.d.ts +13 -0
  55. package/dist/retention/expiry.d.ts.map +1 -0
  56. package/dist/retention/expiry.js +37 -0
  57. package/dist/retention/expiry.js.map +1 -0
  58. package/dist/retention/hash-detect.d.ts +12 -0
  59. package/dist/retention/hash-detect.d.ts.map +1 -0
  60. package/dist/retention/hash-detect.js +29 -0
  61. package/dist/retention/hash-detect.js.map +1 -0
  62. package/dist/retention/storage.d.ts +17 -0
  63. package/dist/retention/storage.d.ts.map +1 -0
  64. package/dist/retention/storage.js +79 -0
  65. package/dist/retention/storage.js.map +1 -0
  66. package/dist/types/audit.d.ts +77 -0
  67. package/dist/types/audit.d.ts.map +1 -0
  68. package/dist/types/audit.js +4 -0
  69. package/dist/types/audit.js.map +1 -0
  70. package/package.json +17 -5
@@ -0,0 +1,34 @@
1
+ import type { AuditFinding } from '../types/audit.js';
2
+ export interface AuditFixitGuide {
3
+ id: string;
4
+ title: string;
5
+ severity: 'critical' | 'medium' | 'low';
6
+ description: string;
7
+ steps: string[];
8
+ command?: string;
9
+ references?: string[];
10
+ }
11
+ /**
12
+ * Get fix-it guide for a specific finding ID.
13
+ */
14
+ export declare function getAuditFixitGuide(id: string): AuditFixitGuide | undefined;
15
+ /**
16
+ * Get all fix-it guides for a list of findings.
17
+ * Pro: all guides. Free: first 3 only.
18
+ */
19
+ export declare function getAuditFixitGuides(findings: AuditFinding[], options: {
20
+ isPro: boolean;
21
+ }): AuditFixitGuide[];
22
+ /**
23
+ * Format fix-it guides as JSON-compatible objects.
24
+ */
25
+ export declare function formatAuditFixitJson(guides: AuditFixitGuide[], isPro: boolean): Array<{
26
+ id: string;
27
+ severity: string;
28
+ title: string;
29
+ description: string;
30
+ steps: string[];
31
+ command?: string;
32
+ references?: string[];
33
+ }>;
34
+ //# sourceMappingURL=audit-fixit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-fixit.d.ts","sourceRoot":"","sources":["../../src/output/audit-fixit.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,KAAK,CAAC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAqOD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAE1E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAC1B,eAAe,EAAE,CAuBnB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,eAAe,EAAE,EACzB,KAAK,EAAE,OAAO,GACb,KAAK,CAAC;IACP,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC,CAqBD"}
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ // ─── Audit Fix-it Guides (F008: 9 + F009: 7 = 16 items) ────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.getAuditFixitGuide = getAuditFixitGuide;
5
+ exports.getAuditFixitGuides = getAuditFixitGuides;
6
+ exports.formatAuditFixitJson = formatAuditFixitJson;
7
+ // ─── F008 Environment Guides ────────────────────────────────
8
+ const AUDIT_FIXIT_DB = {
9
+ 'F008-01': {
10
+ id: 'F008-01',
11
+ title: 'ANTHROPIC_BASE_URL Pointing to Untrusted Host',
12
+ severity: 'critical',
13
+ description: 'CVE-2026-21852 — Attacker can intercept API calls and steal keys via modified base URL.',
14
+ steps: [
15
+ 'Open .env and settings.json files in your project',
16
+ 'Check for ANTHROPIC_BASE_URL entries',
17
+ 'Remove the variable or set it to https://api.anthropic.com',
18
+ 'Rotate your Anthropic API key immediately (the old one may be compromised)',
19
+ 'Restart Claude Code to apply changes',
20
+ ],
21
+ command: '# Remove from .env\nsed -i "/ANTHROPIC_BASE_URL/d" .env\n\n# Or set to official URL\necho "ANTHROPIC_BASE_URL=https://api.anthropic.com" >> .env',
22
+ references: [
23
+ 'https://docs.anthropic.com/en/api/getting-started',
24
+ ],
25
+ },
26
+ 'F008-02': {
27
+ id: 'F008-02',
28
+ title: 'bypassPermissions Enabled',
29
+ severity: 'critical',
30
+ description: 'All permission prompts are automatically approved. Complete bypass of safety checks.',
31
+ steps: [
32
+ 'Open the settings.json file shown in the finding',
33
+ 'Set "bypassPermissions": false or remove the key entirely',
34
+ 'Review any actions taken while bypass was enabled',
35
+ 'Restart Claude Code',
36
+ ],
37
+ command: '# Fix in settings.json — set to false or remove\n# In .claude/settings.json:\n# "bypassPermissions": false',
38
+ },
39
+ 'F008-03': {
40
+ id: 'F008-03',
41
+ title: 'CLAUDE.md Contains Injection Patterns',
42
+ severity: 'critical',
43
+ description: 'Prompt injection vector — attacker can inject commands via local config file.',
44
+ steps: [
45
+ 'Open the CLAUDE.md file flagged in the finding',
46
+ 'Search for suspicious patterns: "ignore previous instructions", "you are now", "secretly"',
47
+ 'Remove or rewrite any directive that overrides safety behavior',
48
+ 'If this file was committed by someone else, investigate the source',
49
+ 'Consider adding CLAUDE.md to code review checklist',
50
+ ],
51
+ references: [
52
+ 'https://owasp.org/www-project-top-10-for-large-language-model-applications/',
53
+ ],
54
+ },
55
+ 'F008-04': {
56
+ id: 'F008-04',
57
+ title: '--dangerously-skip-permissions Usage Detected',
58
+ severity: 'critical',
59
+ description: 'This flag bypasses all permission checks. Real-world case: rm -rf / execution risk.',
60
+ steps: [
61
+ 'Search for "dangerously-skip-permissions" in your Claude Code config files',
62
+ 'Remove any references to this flag from settings.json, .env, and CLAUDE.md',
63
+ 'Use proper permission configuration instead of bypassing',
64
+ 'Review all operations performed while this flag was active',
65
+ ],
66
+ command: '# Search for the flag in your project\ngrep -r "dangerously.skip.permissions" .claude/ .env* CLAUDE.md',
67
+ },
68
+ 'F008-05': {
69
+ id: 'F008-05',
70
+ title: 'disableBypassPermissionsMode Not Configured',
71
+ severity: 'medium',
72
+ description: 'Enterprise protection missing. No centralized policy prevents bypass mode activation.',
73
+ steps: [
74
+ 'Open your global settings (~/.claude/settings.json)',
75
+ 'Add managed-settings section with disableBypassPermissionsMode',
76
+ 'This prevents any project from enabling bypass mode',
77
+ ],
78
+ command: '# Add to ~/.claude/settings.json:\n# {\n# "managed-settings": {\n# "disableBypassPermissionsMode": true\n# }\n# }',
79
+ },
80
+ 'F008-06': {
81
+ id: 'F008-06',
82
+ title: 'Excessive Tool Allowance',
83
+ severity: 'medium',
84
+ description: 'Wildcards or too many tools allowed without restriction. Principle of least privilege violation.',
85
+ steps: [
86
+ 'Open the settings.json file flagged in the finding',
87
+ 'Review the allowedTools list',
88
+ 'Remove wildcard (*) entries',
89
+ 'Restrict to only the tools your workflow actually needs',
90
+ 'Consider using tool-specific matchers instead of broad allowances',
91
+ ],
92
+ command: '# Example: restrict to read-only tools\n# "allowedTools": ["Read", "Glob", "Grep"]',
93
+ },
94
+ 'F008-07': {
95
+ id: 'F008-07',
96
+ title: 'Auto-Accept Permission Mode Active',
97
+ severity: 'medium',
98
+ description: 'Operations run without human review. Permission prompts are automatically accepted.',
99
+ steps: [
100
+ 'Open the settings.json file flagged in the finding',
101
+ 'Change permissionMode to "prompt" or remove it (default is prompt)',
102
+ 'Restart Claude Code to apply',
103
+ ],
104
+ command: '# Remove permissionMode or set to prompt:\n# "permissionMode": "prompt"',
105
+ },
106
+ 'F008-08': {
107
+ id: 'F008-08',
108
+ title: '.claude/ Directory Has Unsafe Permissions',
109
+ severity: 'low',
110
+ description: 'Other users can modify Claude Code configuration. Privilege escalation possible.',
111
+ steps: [
112
+ 'Check current permissions: ls -la .claude/',
113
+ 'Remove group and others write access',
114
+ 'Ensure only the owner can modify the directory',
115
+ ],
116
+ command: 'chmod 700 .claude/',
117
+ },
118
+ 'F008-09': {
119
+ id: 'F008-09',
120
+ title: 'Project-Level Settings Override Global Security',
121
+ severity: 'medium',
122
+ description: 'Project settings weaken global security. CVE-2025-59536 settings downgrade attack pattern.',
123
+ steps: [
124
+ 'Compare project .claude/settings.json with global ~/.claude/settings.json',
125
+ 'Ensure project does not enable bypassPermissions when global has it disabled',
126
+ 'Ensure project does not set auto-accept when global uses prompt mode',
127
+ 'Review project allowedTools against global restrictions',
128
+ ],
129
+ },
130
+ // ─── F009 Hooks Guides ──────────────────────────────────────
131
+ 'F009-01': {
132
+ id: 'F009-01',
133
+ title: 'Network Request in Hook Command',
134
+ severity: 'critical',
135
+ description: 'Hook contains network tools (curl, wget, nc). Data exfiltration channel detected.',
136
+ steps: [
137
+ 'Open the settings.json containing the hook',
138
+ 'Identify the hook with network commands',
139
+ 'Remove or replace with a local-only command',
140
+ 'If network access is needed, use an explicit allowlist of URLs',
141
+ ],
142
+ command: '# Remove the suspicious hook from settings.json hooks section',
143
+ },
144
+ 'F009-02': {
145
+ id: 'F009-02',
146
+ title: 'Data Exfiltration Pattern in Hook',
147
+ severity: 'critical',
148
+ description: 'CVE-2025-59536 — Hook contains data exfiltration patterns like /dev/tcp, base64 piping, DNS tunneling.',
149
+ steps: [
150
+ 'Remove the hook immediately — this is a high-confidence malicious pattern',
151
+ 'Check git blame to identify who added this hook',
152
+ 'Rotate any API keys or secrets that may have been exfiltrated',
153
+ 'Report the incident to your security team',
154
+ ],
155
+ },
156
+ 'F009-03': {
157
+ id: 'F009-03',
158
+ title: 'Reverse Shell Pattern in Hook',
159
+ severity: 'critical',
160
+ description: 'Hook contains reverse shell pattern. Remote access backdoor detected.',
161
+ steps: [
162
+ 'Remove the hook immediately — this is a confirmed backdoor pattern',
163
+ 'Disconnect from the network if possible',
164
+ 'Check for other compromised files in the project',
165
+ 'Report to your security team and rotate all credentials',
166
+ ],
167
+ },
168
+ 'F009-04': {
169
+ id: 'F009-04',
170
+ title: 'Destructive File Operation in Hook',
171
+ severity: 'medium',
172
+ description: 'Hook contains file deletion commands (rm -rf, shred). Data destruction risk.',
173
+ steps: [
174
+ 'Review the hook — is the deletion intentional cleanup or malicious?',
175
+ 'If cleanup: restrict the path to a specific temp directory',
176
+ 'If suspicious: remove the hook entirely',
177
+ 'Consider using safer alternatives (e.g., move to trash instead of delete)',
178
+ ],
179
+ },
180
+ 'F009-05': {
181
+ id: 'F009-05',
182
+ title: 'Environment Variable Access in Hook',
183
+ severity: 'medium',
184
+ description: 'Hook reads environment variables. Credential collection risk (API keys, secrets).',
185
+ steps: [
186
+ 'Review the hook — is the env var access needed?',
187
+ 'Remove references to sensitive variables ($ANTHROPIC_API_KEY, $AWS_SECRET_ACCESS_KEY)',
188
+ 'If env access is needed, restrict to specific non-sensitive variables',
189
+ ],
190
+ },
191
+ 'F009-06': {
192
+ id: 'F009-06',
193
+ title: 'Hooks in Project-Level Settings',
194
+ severity: 'medium',
195
+ description: 'Hooks in project settings auto-execute on all collaborator machines. Lateral movement risk.',
196
+ steps: [
197
+ 'Move hooks from project .claude/settings.json to user-level ~/.claude/settings.json',
198
+ 'If project hooks are needed, document them in CLAUDE.md and get team approval',
199
+ 'Add hook review to your code review checklist',
200
+ ],
201
+ },
202
+ 'F009-07': {
203
+ id: 'F009-07',
204
+ title: 'Obfuscated Command in Hook',
205
+ severity: 'critical',
206
+ description: 'Hook contains obfuscated command (base64+eval). Detection evasion attempt.',
207
+ steps: [
208
+ 'Remove the hook immediately — obfuscation in hooks is almost always malicious',
209
+ 'Decode the obfuscated content to understand what it does',
210
+ 'Report to your security team',
211
+ 'Replace with plain-text equivalent if the functionality is legitimate',
212
+ ],
213
+ command: '# Decode base64 content to inspect:\necho "<base64-content>" | base64 -d',
214
+ },
215
+ };
216
+ /**
217
+ * Get fix-it guide for a specific finding ID.
218
+ */
219
+ function getAuditFixitGuide(id) {
220
+ return AUDIT_FIXIT_DB[id];
221
+ }
222
+ /**
223
+ * Get all fix-it guides for a list of findings.
224
+ * Pro: all guides. Free: first 3 only.
225
+ */
226
+ function getAuditFixitGuides(findings, options) {
227
+ const guides = [];
228
+ const seen = new Set();
229
+ // Sort: critical first, then medium, then low
230
+ const sorted = [...findings].sort((a, b) => {
231
+ const order = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
232
+ return order[a.severity] - order[b.severity];
233
+ });
234
+ for (const finding of sorted) {
235
+ if (seen.has(finding.id))
236
+ continue;
237
+ const guide = AUDIT_FIXIT_DB[finding.id];
238
+ if (guide) {
239
+ guides.push(guide);
240
+ seen.add(finding.id);
241
+ }
242
+ }
243
+ if (!options.isPro) {
244
+ return guides.slice(0, 3);
245
+ }
246
+ return guides;
247
+ }
248
+ /**
249
+ * Format fix-it guides as JSON-compatible objects.
250
+ */
251
+ function formatAuditFixitJson(guides, isPro) {
252
+ return guides.map((g) => {
253
+ const base = {
254
+ id: g.id,
255
+ severity: g.severity,
256
+ title: g.title,
257
+ description: g.description,
258
+ steps: isPro ? g.steps : [g.steps[0]],
259
+ };
260
+ if (isPro && g.command)
261
+ base.command = g.command;
262
+ if (isPro && g.references)
263
+ base.references = g.references;
264
+ return base;
265
+ });
266
+ }
267
+ //# sourceMappingURL=audit-fixit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-fixit.js","sourceRoot":"","sources":["../../src/output/audit-fixit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { AuditResult } from '../types/audit.js';
2
+ import type { FeatureGate } from '../license/types.js';
3
+ /**
4
+ * Format audit result as PRD box-style terminal output.
5
+ */
6
+ export declare function formatAuditTerminal(result: AuditResult, gate: FeatureGate, options: {
7
+ fix: boolean;
8
+ }): string;
9
+ /**
10
+ * Format audit result as JSON output.
11
+ */
12
+ export declare function formatAuditJson(result: AuditResult, gate: FeatureGate, options: {
13
+ fix: boolean;
14
+ }): string;
15
+ //# sourceMappingURL=audit-terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-terminal.d.ts","sourceRoot":"","sources":["../../src/output/audit-terminal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAgB,MAAM,mBAAmB,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAkEvD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,GACxB,MAAM,CAmIR;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,GACxB,MAAM,CAUR"}
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ // ─── Audit Terminal Output (PRD box format) ─────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.formatAuditTerminal = formatAuditTerminal;
5
+ exports.formatAuditJson = formatAuditJson;
6
+ const audit_fixit_js_1 = require("./audit-fixit.js");
7
+ const c = {
8
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
9
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
10
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
11
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
12
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
13
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
14
+ };
15
+ const W = 53; // inner width of box
16
+ function pad(text, width) {
17
+ // strip ANSI for length calc
18
+ const stripped = text.replace(/\x1b\[[0-9;]*m/g, '');
19
+ const diff = width - stripped.length;
20
+ return diff > 0 ? text + ' '.repeat(diff) : text;
21
+ }
22
+ function boxTop() {
23
+ return '\u2554' + '\u2550'.repeat(W) + '\u2557';
24
+ }
25
+ function boxMid() {
26
+ return '\u2560' + '\u2550'.repeat(W) + '\u2563';
27
+ }
28
+ function boxBot() {
29
+ return '\u255A' + '\u2550'.repeat(W) + '\u255D';
30
+ }
31
+ function boxLine(text) {
32
+ return '\u2551 ' + pad(text, W - 4) + ' \u2551';
33
+ }
34
+ function severityIcon(severity) {
35
+ switch (severity) {
36
+ case 'critical': return c.red('\u{1F534}');
37
+ case 'high': return c.red('\u{1F534}');
38
+ case 'medium': return c.yellow('\u{1F7E1}');
39
+ case 'low': return c.cyan('\u{1F535}');
40
+ case 'info': return c.dim('\u2139\uFE0F');
41
+ default: return '';
42
+ }
43
+ }
44
+ function severityLabel(severity) {
45
+ switch (severity) {
46
+ case 'critical': return c.red('CRITICAL');
47
+ case 'high': return c.red('HIGH');
48
+ case 'medium': return c.yellow('WARNING');
49
+ case 'low': return c.cyan('INFO');
50
+ case 'info': return c.dim('INFO');
51
+ default: return severity.toUpperCase();
52
+ }
53
+ }
54
+ function gradeColor(grade) {
55
+ if (grade === 'A' || grade === 'B')
56
+ return c.green;
57
+ if (grade === 'C')
58
+ return c.yellow;
59
+ return c.red;
60
+ }
61
+ function formatFindingLine(finding) {
62
+ return `${severityIcon(finding.severity)} ${severityLabel(finding.severity)}: ${finding.title}`;
63
+ }
64
+ /**
65
+ * Format audit result as PRD box-style terminal output.
66
+ */
67
+ function formatAuditTerminal(result, gate, options) {
68
+ const lines = [];
69
+ const isPro = gate.isPro;
70
+ // Header
71
+ const headerLabel = isPro
72
+ ? `Claude Code Environment Audit ${c.green('[Pro]')}`
73
+ : 'Claude Code Environment Audit';
74
+ lines.push(boxTop());
75
+ lines.push(boxLine(c.bold(headerLabel)));
76
+ lines.push(boxMid());
77
+ // Environment findings (F008)
78
+ const envFindings = result.environment;
79
+ const hookFindings = result.hooks;
80
+ if (envFindings.length === 0 && hookFindings.length === 0 && result.summary.total === 0) {
81
+ lines.push(boxLine(c.green('\u2705 No security issues detected')));
82
+ }
83
+ else {
84
+ // Environment findings
85
+ for (const f of envFindings) {
86
+ lines.push(boxLine(formatFindingLine(f)));
87
+ }
88
+ // Pass indicators for free checks with no findings
89
+ if (!isPro) {
90
+ const freeIds = ['F008-01', 'F008-02', 'F008-03'];
91
+ const foundFreeIds = new Set(envFindings.map((f) => f.id));
92
+ for (const id of freeIds) {
93
+ if (!foundFreeIds.has(id)) {
94
+ const passLabel = id === 'F008-01' ? 'No ANTHROPIC_BASE_URL issues'
95
+ : id === 'F008-02' ? 'bypassPermissions not enabled'
96
+ : 'No CLAUDE.md injection patterns';
97
+ lines.push(boxLine(`${c.green('\u2705')} PASS: ${passLabel}`));
98
+ }
99
+ }
100
+ }
101
+ // Hooks section (Pro only)
102
+ if (isPro && hookFindings.length > 0) {
103
+ lines.push(boxLine(c.dim('\u2500\u2500 Hooks Analysis ' + '\u2500'.repeat(30))));
104
+ for (const f of hookFindings) {
105
+ lines.push(boxLine(formatFindingLine(f)));
106
+ }
107
+ }
108
+ else if (isPro && hookFindings.length === 0) {
109
+ lines.push(boxLine(c.dim('\u2500\u2500 Hooks Analysis ' + '\u2500'.repeat(30))));
110
+ lines.push(boxLine(`${c.green('\u2705')} PASS: No malicious hook patterns detected`));
111
+ }
112
+ }
113
+ // Score section
114
+ lines.push(boxMid());
115
+ const gc = gradeColor(result.score.grade);
116
+ lines.push(boxLine(`Environment Score: ${gc(result.score.grade)} (${result.score.total}/100)`));
117
+ // Action line
118
+ if (result.summary.critical > 0 || result.summary.medium > 0) {
119
+ const parts = [];
120
+ if (result.summary.critical > 0)
121
+ parts.push(`${result.summary.critical} critical`);
122
+ const warnings = result.summary.medium + result.summary.low;
123
+ if (warnings > 0)
124
+ parts.push(`${warnings} warning`);
125
+ lines.push(boxLine(c.yellow(`\u26A0\uFE0F Fix ${parts.join(' + ')} issues`)));
126
+ }
127
+ // Free tier upsell
128
+ if (!isPro && result.summary.proOnly > 0) {
129
+ lines.push(boxLine(c.yellow(`\u26A0\uFE0F ${result.summary.proOnly} additional issues found \u2014 upgrade to Pro`)));
130
+ }
131
+ lines.push(boxBot());
132
+ // Fix-it guides below the box
133
+ if (options.fix) {
134
+ const allFindings = [...result.environment, ...result.hooks];
135
+ const guides = (0, audit_fixit_js_1.getAuditFixitGuides)(allFindings, { isPro });
136
+ if (guides.length > 0) {
137
+ lines.push('');
138
+ lines.push(c.bold('\u2501\u2501\u2501 Fix-it Guide \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501'));
139
+ lines.push('');
140
+ for (const guide of guides) {
141
+ const icon = guide.severity === 'critical' ? c.red('CRITICAL') : c.yellow('WARNING');
142
+ lines.push(` ${icon} ${c.bold(guide.title)}`);
143
+ lines.push(` ${c.dim(guide.description)}`);
144
+ if (isPro) {
145
+ for (let i = 0; i < guide.steps.length; i++) {
146
+ lines.push(` ${i + 1}. ${guide.steps[i]}`);
147
+ }
148
+ if (guide.command) {
149
+ lines.push('');
150
+ lines.push(c.dim(' Command:'));
151
+ for (const cmdLine of guide.command.split('\n')) {
152
+ lines.push(` ${c.cyan(cmdLine)}`);
153
+ }
154
+ }
155
+ if (guide.references && guide.references.length > 0) {
156
+ lines.push(c.dim(' References:'));
157
+ for (const ref of guide.references) {
158
+ lines.push(` - ${ref}`);
159
+ }
160
+ }
161
+ }
162
+ else {
163
+ lines.push(` 1. ${guide.steps[0]}`);
164
+ if (guide.steps.length > 1) {
165
+ lines.push(c.dim(` ... ${guide.steps.length - 1} more steps (Pro)`));
166
+ }
167
+ }
168
+ lines.push('');
169
+ }
170
+ if (!isPro) {
171
+ const total = (0, audit_fixit_js_1.getAuditFixitGuides)(allFindings, { isPro: true }).length;
172
+ if (total > guides.length) {
173
+ lines.push(c.dim(` Showing ${guides.length} of ${total} guides. Upgrade to Pro for all guides.`));
174
+ lines.push('');
175
+ }
176
+ }
177
+ }
178
+ }
179
+ // Upgrade prompt
180
+ if (!isPro && !options.fix && result.summary.proOnly > 0) {
181
+ lines.push('');
182
+ lines.push(c.yellow(' Upgrade to Pro for full audit + hooks analysis + fix-it guides'));
183
+ lines.push(c.yellow(' https://shield.codemeant.dev/#pricing'));
184
+ lines.push('');
185
+ }
186
+ return lines.join('\n');
187
+ }
188
+ /**
189
+ * Format audit result as JSON output.
190
+ */
191
+ function formatAuditJson(result, gate, options) {
192
+ const output = { ...result };
193
+ if (options.fix) {
194
+ const allFindings = [...result.environment, ...result.hooks];
195
+ const guides = (0, audit_fixit_js_1.getAuditFixitGuides)(allFindings, { isPro: gate.isPro });
196
+ output.fixit = (0, audit_fixit_js_1.formatAuditFixitJson)(guides, gate.isPro);
197
+ }
198
+ return JSON.stringify(output, null, 2);
199
+ }
200
+ //# sourceMappingURL=audit-terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-terminal.js","sourceRoot":"","sources":["../../src/output/audit-terminal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface ExpiryCheck {
2
+ hasAudit: boolean;
3
+ isExpired: boolean;
4
+ daysSinceAudit: number;
5
+ lastAuditAt: string;
6
+ message?: string;
7
+ }
8
+ /**
9
+ * Check if the last audit for a project is stale (>7 days).
10
+ * Used by scan command to show retention warning.
11
+ */
12
+ export declare function checkAuditExpiry(projectDir: string): ExpiryCheck;
13
+ //# sourceMappingURL=expiry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expiry.d.ts","sourceRoot":"","sources":["../../src/retention/expiry.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,CA2BhE"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ // ─── Audit Expiry Detection ─────────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.checkAuditExpiry = checkAuditExpiry;
5
+ const storage_js_1 = require("./storage.js");
6
+ const EXPIRY_DAYS = 7;
7
+ const MS_PER_DAY = 24 * 60 * 60 * 1000;
8
+ /**
9
+ * Check if the last audit for a project is stale (>7 days).
10
+ * Used by scan command to show retention warning.
11
+ */
12
+ function checkAuditExpiry(projectDir) {
13
+ const state = (0, storage_js_1.readAuditState)(projectDir);
14
+ if (!state) {
15
+ return {
16
+ hasAudit: false,
17
+ isExpired: false,
18
+ daysSinceAudit: -1,
19
+ lastAuditAt: '',
20
+ message: 'No previous audit found. Run `project-shield audit` to check your Claude Code environment.',
21
+ };
22
+ }
23
+ const lastAudit = new Date(state.lastAuditAt).getTime();
24
+ const now = Date.now();
25
+ const daysSince = Math.floor((now - lastAudit) / MS_PER_DAY);
26
+ const isExpired = daysSince >= EXPIRY_DAYS;
27
+ return {
28
+ hasAudit: true,
29
+ isExpired,
30
+ daysSinceAudit: daysSince,
31
+ lastAuditAt: state.lastAuditAt,
32
+ message: isExpired
33
+ ? `Last audit: ${daysSince} days ago. Run \`project-shield audit\` for latest results.`
34
+ : undefined,
35
+ };
36
+ }
37
+ //# sourceMappingURL=expiry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expiry.js","sourceRoot":"","sources":["../../src/retention/expiry.ts"],"names":[],"mappings":";AAAA,+DAA+D;;AAmB/D,4CA2BC;AA5CD,6CAA8C;AAE9C,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAUvC;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,UAAkB;IACjD,MAAM,KAAK,GAAG,IAAA,2BAAc,EAAC,UAAU,CAAC,CAAC;IAEzC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,SAAS,EAAE,KAAK;YAChB,cAAc,EAAE,CAAC,CAAC;YAClB,WAAW,EAAE,EAAE;YACf,OAAO,EAAE,4FAA4F;SACtG,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;IACxD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,UAAU,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,SAAS,IAAI,WAAW,CAAC;IAE3C,OAAO;QACL,QAAQ,EAAE,IAAI;QACd,SAAS;QACT,cAAc,EAAE,SAAS;QACzB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,SAAS;YAChB,CAAC,CAAC,eAAe,SAAS,6DAA6D;YACvF,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface HashChangeResult {
2
+ hasChanged: boolean;
3
+ previousHash: string;
4
+ currentHash: string;
5
+ message?: string;
6
+ }
7
+ /**
8
+ * Compare stored settings hash with current hash.
9
+ * Returns change detection result.
10
+ */
11
+ export declare function detectHashChange(projectDir: string, currentHash: string): HashChangeResult;
12
+ //# sourceMappingURL=hash-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash-detect.d.ts","sourceRoot":"","sources":["../../src/retention/hash-detect.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,gBAAgB,CAqBlB"}