gsc-cli 2.1.0 → 2.2.2

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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/AUTH.md +4 -1
  3. data/README.md +448 -408
  4. data/bin/gsc +28067 -5661
  5. data/dist/gsc +29121 -5046
  6. data/lib/gsc/aio_hunter.rb +343 -0
  7. data/lib/gsc/answer_synthesizer.rb +157 -0
  8. data/lib/gsc/api.rb +53 -1
  9. data/lib/gsc/auth.rb +26 -0
  10. data/lib/gsc/brand_segmenter.rb +140 -0
  11. data/lib/gsc/cache_manager.rb +806 -0
  12. data/lib/gsc/cannibalization_analyzer.rb +141 -0
  13. data/lib/gsc/canonical_chains.rb +367 -0
  14. data/lib/gsc/citation_simulator.rb +339 -0
  15. data/lib/gsc/cli/aio_hunter.rb +154 -0
  16. data/lib/gsc/cli/analytics.rb +788 -0
  17. data/lib/gsc/cli/audit.rb +1976 -0
  18. data/lib/gsc/cli/base.rb +384 -0
  19. data/lib/gsc/cli/cache.rb +266 -0
  20. data/lib/gsc/cli/canonical.rb +223 -0
  21. data/lib/gsc/cli/citation_simulator.rb +152 -0
  22. data/lib/gsc/cli/dashboard.rb +354 -0
  23. data/lib/gsc/cli/doctor.rb +129 -0
  24. data/lib/gsc/cli/eeat.rb +125 -0
  25. data/lib/gsc/cli/ga4.rb +852 -0
  26. data/lib/gsc/cli/growth.rb +650 -0
  27. data/lib/gsc/cli/hreflang.rb +164 -0
  28. data/lib/gsc/cli/image_seo.rb +162 -0
  29. data/lib/gsc/cli/indexing.rb +458 -0
  30. data/lib/gsc/cli/intent_shift.rb +125 -0
  31. data/lib/gsc/cli/keyword_value.rb +134 -0
  32. data/lib/gsc/cli/keywords.rb +795 -0
  33. data/lib/gsc/cli/landing_roi.rb +308 -0
  34. data/lib/gsc/cli/low_ctr.rb +213 -0
  35. data/lib/gsc/cli/mobile_parity.rb +150 -0
  36. data/lib/gsc/cli/report.rb +100 -0
  37. data/lib/gsc/cli/rich_results.rb +172 -0
  38. data/lib/gsc/cli/schema_generate.rb +149 -0
  39. data/lib/gsc/cli/seasonal.rb +232 -0
  40. data/lib/gsc/cli/security.rb +153 -0
  41. data/lib/gsc/cli/setup.rb +1291 -0
  42. data/lib/gsc/cli/sitemap_tree.rb +143 -0
  43. data/lib/gsc/cli/skill_pack.rb +62 -0
  44. data/lib/gsc/cli/soft_404.rb +199 -0
  45. data/lib/gsc/cli/sparkline.rb +227 -0
  46. data/lib/gsc/cli/watchdog.rb +150 -0
  47. data/lib/gsc/cli/zombie_purger.rb +208 -0
  48. data/lib/gsc/cli.rb +707 -5265
  49. data/lib/gsc/cli_advanced.rb +987 -44
  50. data/lib/gsc/client.rb +17 -2
  51. data/lib/gsc/color.rb +16 -1
  52. data/lib/gsc/command_registry.rb +47 -9
  53. data/lib/gsc/config.rb +2 -2
  54. data/lib/gsc/ctr_curve.rb +115 -0
  55. data/lib/gsc/decay_predictor.rb +322 -0
  56. data/lib/gsc/doctor.rb +434 -0
  57. data/lib/gsc/eeat_auditor.rb +428 -0
  58. data/lib/gsc/entity_auditor.rb +229 -0
  59. data/lib/gsc/firewall_scanner.rb +733 -0
  60. data/lib/gsc/geo_auditor.rb +368 -0
  61. data/lib/gsc/google_trends.rb +8 -1
  62. data/lib/gsc/heading_validator.rb +283 -0
  63. data/lib/gsc/hreflang_validator.rb +412 -0
  64. data/lib/gsc/image_seo.rb +286 -0
  65. data/lib/gsc/indexing_queue.rb +179 -0
  66. data/lib/gsc/indexnow.rb +93 -0
  67. data/lib/gsc/intent_shift.rb +188 -0
  68. data/lib/gsc/internal_links.rb +153 -36
  69. data/lib/gsc/keyword_value.rb +191 -0
  70. data/lib/gsc/landing_roi.rb +195 -0
  71. data/lib/gsc/llms_generator.rb +343 -22
  72. data/lib/gsc/low_ctr_rewriter.rb +408 -0
  73. data/lib/gsc/mobile_parity.rb +222 -0
  74. data/lib/gsc/network_tracer.rb +8 -1
  75. data/lib/gsc/page_analyzer.rb +47 -7
  76. data/lib/gsc/prompts.rb +38 -29
  77. data/lib/gsc/questions_harvester.rb +178 -0
  78. data/lib/gsc/report_generator.rb +461 -0
  79. data/lib/gsc/rich_results.rb +388 -0
  80. data/lib/gsc/robots_checker.rb +46 -15
  81. data/lib/gsc/schema_generator.rb +788 -0
  82. data/lib/gsc/schema_validator.rb +36 -38
  83. data/lib/gsc/seasonal_predictor.rb +381 -0
  84. data/lib/gsc/security_scanner.rb +496 -0
  85. data/lib/gsc/serp_feature_detector.rb +359 -0
  86. data/lib/gsc/serp_preview.rb +108 -22
  87. data/lib/gsc/site_crawler.rb +113 -21
  88. data/lib/gsc/sitemap_loader.rb +15 -4
  89. data/lib/gsc/sitemap_tree.rb +301 -0
  90. data/lib/gsc/skill_pack.rb +195 -0
  91. data/lib/gsc/soft_404_analyzer.rb +385 -0
  92. data/lib/gsc/sparkline.rb +171 -0
  93. data/lib/gsc/speed_correlator.rb +416 -0
  94. data/lib/gsc/striking_playbook.rb +190 -0
  95. data/lib/gsc/title_optimizer.rb +420 -0
  96. data/lib/gsc/vault.rb +260 -0
  97. data/lib/gsc/version.rb +1 -1
  98. data/lib/gsc/watchdog.rb +235 -0
  99. data/lib/gsc/zombie_purger.rb +366 -0
  100. data/lib/gsc.rb +118 -0
  101. metadata +75 -1
@@ -0,0 +1,153 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'json'
5
+ require_relative 'base'
6
+ require_relative '../security_scanner'
7
+ require_relative '../color'
8
+
9
+ module GSC
10
+ class CLI
11
+ module Security
12
+ module_function
13
+
14
+ def run(command, target, extra, options, api = nil, site_url = nil, hostname = nil)
15
+ target_url = target || options[:url] || hostname || (site_url ? site_url.sub(/^sc-domain:/, '') : nil) || (Config.default_domain rescue nil)
16
+ unless target_url
17
+ if options[:json]
18
+ puts JSON.pretty_generate({ error: 'Target URL or domain required. Example: gsc security https://mysite.com' })
19
+ else
20
+ puts Color.c("❌ Error: Target URL or domain required. Example: gsc security https://mysite.com", Color::RED, Color::BOLD)
21
+ end
22
+ return
23
+ end
24
+ target_url = "https://#{target_url}" unless target_url =~ %r{^https?://}
25
+
26
+ scanner = GSC::SecurityScanner.new(target_url, options)
27
+ result = scanner.audit
28
+
29
+ if options[:json]
30
+ puts JSON.pretty_generate(result)
31
+ return
32
+ end
33
+
34
+ render_security_audit(result, options)
35
+ end
36
+
37
+ def render_security_audit(data, options)
38
+ puts "\n" + Color.cyan("╔" + "═" * 78 + "╗")
39
+ puts Color.cyan("║") + Color.bold(" 🔒 SECURITY HEADERS & HTTPS MIXED CONTENT AUDITOR ") + Color.cyan("║")
40
+ puts Color.cyan("╚" + "═" * 78 + "╝")
41
+ puts Color.gray(" Target URL: ") + Color.bold(data[:target])
42
+ puts Color.gray(" Effective URL: ") + Color.dim(data[:effective_url].to_s)
43
+
44
+ # Score & Grade
45
+ grade_color = case data[:grade]
46
+ when 'A+', 'A' then Color::GREEN
47
+ when 'B' then Color::CYAN
48
+ when 'C' then Color::YELLOW
49
+ else Color::RED
50
+ end
51
+
52
+ puts Color.gray(" Security Posture: ") + Color.c("#{data[:score]}/100 [Grade #{data[:grade]}]", grade_color, Color::BOLD)
53
+ puts Color.gray(" Verdict: ") + Color.c(data[:verdict].to_s, grade_color)
54
+ puts Color.cyan("─" * 80)
55
+
56
+ # 1. SSL/TLS Certificate
57
+ ssl = data[:ssl] || {}
58
+ puts "\n" + Color.bold("🔐 SSL/TLS CERTIFICATE STATUS:")
59
+ if ssl[:status] == :valid
60
+ puts " • Status: " + Color.green(Color.bold("VALID & SECURE")) + Color.gray(" (#{ssl[:days_remaining]} days remaining)")
61
+ puts " • Valid Period: #{ssl[:valid_from][0..9]} → #{ssl[:valid_to][0..9]}"
62
+ puts " • Issuer: #{ssl[:issuer]}"
63
+ puts " • Subject / SAN: #{ssl[:subject]} (#{ssl[:san_count]} alternate names)"
64
+ elsif ssl[:status] == :not_https
65
+ puts " • Status: " + Color.red(Color.bold("NOT SERVED OVER HTTPS"))
66
+ else
67
+ puts " • Status: " + Color.red(Color.bold("WARNING: #{ssl[:message] || ssl[:status]}"))
68
+ end
69
+
70
+ # 2. HSTS Preload Eligibility
71
+ hsts = data[:hsts_preload] || {}
72
+ puts "\n" + Color.bold("🚀 HSTS PRELOAD STATUS (Google Chrome Preload List):")
73
+ if hsts[:eligible]
74
+ puts " • Eligibility: " + Color.green(Color.bold("✓ ELIGIBLE FOR HSTS PRELOAD"))
75
+ puts " • Header: " + Color.dim(hsts[:current_header].to_s)
76
+ else
77
+ puts " • Eligibility: " + Color.yellow(Color.bold("NOT CURRENTLY ELIGIBLE"))
78
+ (hsts[:reasons] || []).each do |reason|
79
+ puts " ↳ " + Color.gray(reason)
80
+ end
81
+ end
82
+
83
+ # 3. Security Headers Audit Table
84
+ headers = data[:headers] || {}
85
+ puts "\n" + Color.bold("🛡️ ENTERPRISE SECURITY HEADERS:")
86
+
87
+ (headers[:present] || []).each do |p|
88
+ q_badge = case p[:quality]
89
+ when :optimal then Color.green("[OPTIMAL]")
90
+ when :acceptable then Color.cyan("[ACCEPTABLE]")
91
+ else Color.yellow("[SUBOPTIMAL]")
92
+ end
93
+ puts " ✓ #{Color.bold(p[:header].ljust(27))} #{q_badge} #{Color.dim(p[:details])}"
94
+ end
95
+
96
+ (headers[:missing] || []).each do |m|
97
+ puts " ✗ #{Color.red(Color.bold(m[:header].ljust(27)))} #{Color.red("[MISSING -#{m[:weight]}pts]")} #{Color.gray(m[:desc])}"
98
+ end
99
+
100
+ # 4. Leakage Headers
101
+ leaks = headers[:leakage] || []
102
+ if leaks.any?
103
+ puts "\n" + Color.bold("⚠️ SERVER FINGERPRINTING & LEAKAGE HEADERS:")
104
+ leaks.each do |l|
105
+ puts " • #{Color.yellow(l[:header])}: #{Color.dim(l[:value])} #{Color.gray("(Reveals server version to attackers)")}"
106
+ end
107
+ end
108
+
109
+ # 5. Mixed Content
110
+ mixed = data[:mixed_content] || {}
111
+ puts "\n" + Color.bold("⚡ HTTPS MIXED CONTENT STATUS:")
112
+ if mixed[:total] == 0
113
+ puts " " + Color.green("✓ Zero mixed content detected! All scripts, frames, and media are securely loaded over HTTPS.")
114
+ else
115
+ if mixed[:active].any?
116
+ puts " 🚨 " + Color.red(Color.bold("ACTIVE MIXED CONTENT (#{mixed[:active].size} items - HARD BLOCKED BY BROWSERS):"))
117
+ mixed[:active].first(5).each do |item|
118
+ puts " • #{item[:type]}: #{Color.yellow(item[:url])}"
119
+ end
120
+ end
121
+ if mixed[:passive].any?
122
+ puts " ⚠️ " + Color.yellow(Color.bold("PASSIVE MIXED CONTENT (#{mixed[:passive].size} images/media - DEGRADES PADLOCK):"))
123
+ mixed[:passive].first(5).each do |item|
124
+ puts " • #{item[:type]}: #{Color.dim(item[:url])}"
125
+ end
126
+ end
127
+ end
128
+
129
+ # 6. Recommendations
130
+ recs = data[:recommendations] || []
131
+ if recs.any?
132
+ puts "\n" + Color.bold("📋 ACTIONABLE SECURITY RECOMMENDATIONS:")
133
+ recs.each_with_index do |rec, idx|
134
+ puts " #{idx + 1}. #{rec}"
135
+ end
136
+ end
137
+
138
+ # 7. 1-Click Server Directives
139
+ rules = data[:server_rules] || {}
140
+ if rules[:nginx] && !rules[:nginx].empty?
141
+ puts "\n" + Color.cyan("─" * 80)
142
+ puts Color.bold("💻 1-CLICK SERVER FIX RULES (Nginx):")
143
+ puts Color.dim(rules[:nginx])
144
+ puts "\n" + Color.bold("💻 1-CLICK SERVER FIX RULES (Apache .htaccess):")
145
+ puts Color.dim(rules[:apache])
146
+ puts "\n" + Color.bold("💻 1-CLICK SERVER FIX RULES (Vercel / Netlify _headers):")
147
+ puts Color.dim(rules[:vercel_netlify])
148
+ end
149
+ puts Color.cyan("=" * 80) + "\n"
150
+ end
151
+ end
152
+ end
153
+ end