sharkit 1.0.0.dev3__tar.gz → 1.0.0.dev5__tar.gz

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 (79) hide show
  1. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/PKG-INFO +1 -1
  2. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/pyproject.toml +5 -1
  3. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/commands/builtins.py +2 -3
  4. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/base.py +1 -1
  5. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/analytics/images/exif_reader.py +5 -2
  6. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/domains/dns_lookup.py +8 -7
  7. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/network/port_scanner.py +3 -3
  8. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/network/ssl_check.py +36 -18
  9. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/.gitignore +0 -0
  10. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/LICENSE +0 -0
  11. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/README.md +0 -0
  12. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/__init__.py +0 -0
  13. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/__main__.py +0 -0
  14. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/app.py +0 -0
  15. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/commands/__init__.py +0 -0
  16. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/commands/base.py +0 -0
  17. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/commands/registry.py +0 -0
  18. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/config/__init__.py +0 -0
  19. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/config/manager.py +0 -0
  20. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/config/paths.py +0 -0
  21. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/console/__init__.py +0 -0
  22. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/console/completion.py +0 -0
  23. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/console/prompt.py +0 -0
  24. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/console/repl.py +0 -0
  25. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/exceptions.py +0 -0
  26. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/history/__init__.py +0 -0
  27. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/history/manager.py +0 -0
  28. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/network/__init__.py +0 -0
  29. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/network/client.py +0 -0
  30. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/output/__init__.py +0 -0
  31. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/output/renderer.py +0 -0
  32. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/output/theme.py +0 -0
  33. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/__init__.py +0 -0
  34. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/flatten_tools.sh +0 -0
  35. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/geoint/recon/wifi/mylnikov.py +0 -0
  36. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/humint/__init__.py +0 -0
  37. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/humint/factcheck/truthcheck.py +0 -0
  38. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/humint/factcheck/verifact.py +0 -0
  39. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/loader.py +0 -0
  40. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/manager.py +0 -0
  41. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/analytics/crypto/mempool.py +0 -0
  42. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/analytics/hashes/hash_decrypt.py +0 -0
  43. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/analytics/hashes/hash_lookup.py +0 -0
  44. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/analytics/text/base64_tool.py +0 -0
  45. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/analytics/text/text_entropy.py +0 -0
  46. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/gather/scraperx.py +0 -0
  47. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/gather/scweet.py +0 -0
  48. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/darkweb/ahmia_search.py +0 -0
  49. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/darkweb/pyahmia.py +0 -0
  50. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/domains/cve_search.py +0 -0
  51. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/domains/otx_query.py +0 -0
  52. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/domains/urlhaus_check.py +0 -0
  53. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/domains/whois_lookup.py +0 -0
  54. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/emails/email_reputation.py +0 -0
  55. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/emails/email_security.py +0 -0
  56. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/emails/holehe.py +0 -0
  57. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/emails/mailaccess.py +0 -0
  58. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/emails/theharvester.py +0 -0
  59. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/hybrid/blackbird.py +0 -0
  60. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/leaks/circl_hashlookup.py +0 -0
  61. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/leaks/hibp_passwords.py +0 -0
  62. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/leaks/leak_check.py +0 -0
  63. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/leaks/psbdmp.py +0 -0
  64. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/leaks/xposed_or_not.py +0 -0
  65. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/network/bgpv6.py +0 -0
  66. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/network/http_headers.py +0 -0
  67. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/network/ip_geolocate.py +0 -0
  68. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/network/ip_info.py +0 -0
  69. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/network/robtex.py +0 -0
  70. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/network/shodan_internetdb.py +0 -0
  71. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/phones/phoneinfoga.py +0 -0
  72. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/usernames/maigret.py +0 -0
  73. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/usernames/sherlock.py +0 -0
  74. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/usernames/social_analyzer.py +0 -0
  75. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/usernames/socialscan.py +0 -0
  76. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/usernames/socid_extractor.py +0 -0
  77. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/web/robots_check.py +0 -0
  78. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/osint/recon/web/wayback_check.py +0 -0
  79. {sharkit-1.0.0.dev3 → sharkit-1.0.0.dev5}/src/sharkit/tools/registry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sharkit
3
- Version: 1.0.0.dev3
3
+ Version: 1.0.0.dev5
4
4
  Summary: OSINT / HUMINT / GEOINT research framework
5
5
  Project-URL: Homepage, https://github.com/sshsrv/sharkit
6
6
  Project-URL: Repository, https://github.com/sshsrv/sharkit
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sharkit"
3
- version = "1.0.0.dev3"
3
+ version = "1.0.0.dev5"
4
4
  description = "OSINT / HUMINT / GEOINT research framework"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -89,6 +89,10 @@ no_implicit_optional = true
89
89
  warn_redundant_casts = true
90
90
  warn_unused_ignores = true
91
91
 
92
+ [[tool.mypy.overrides]]
93
+ module = "exifread"
94
+ ignore_missing_imports = true
95
+
92
96
  [tool.pytest.ini_options]
93
97
  testpaths = ["tests"]
94
98
  pythonpath = ["src"]
@@ -312,7 +312,7 @@ class ShowCommand(Command):
312
312
  if not all_tools:
313
313
  return "No tools available."
314
314
 
315
- def matches_category(tool_path: str, tool_cls: type) -> bool:
315
+ def matches_category(tool_path: str, tool_cls: type[Tool]) -> bool:
316
316
  if category is None:
317
317
  return True
318
318
 
@@ -320,8 +320,7 @@ class ShowCommand(Command):
320
320
  tool_category = (tool_cls.metadata.category or "").lower()
321
321
  first_segment = tool_category.split(".")[0]
322
322
  return (
323
- normalized_category == tool_category
324
- or normalized_category == first_segment
323
+ normalized_category in (tool_category, first_segment)
325
324
  or normalized_category in tool_category
326
325
  or tool_path.lower().startswith(f"{normalized_category}/")
327
326
  )
@@ -38,7 +38,7 @@ def parse_bool(value: str | None) -> bool:
38
38
 
39
39
  @dataclass(frozen=True)
40
40
  class ToolInstallSpec:
41
- git_url: str
41
+ git_url: str | None
42
42
  requirements_file: str | None = None
43
43
  pip_args: list[str] = field(default_factory=list)
44
44
  entry: str | None = None
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import os
4
+ from typing import Any
4
5
 
5
6
  from sharkit.tools.base import (
6
7
  ExecutionContext,
@@ -45,10 +46,12 @@ TIMESTAMP_TAGS = {
45
46
  ALL_TAGS = GPS_TAGS | CAMERA_TAGS | TIMESTAMP_TAGS
46
47
 
47
48
 
48
- def _dms_to_decimal(dms_tag: object, ref_tag: object) -> float | None:
49
+ def _dms_to_decimal(dms_tag: Any, ref_tag: Any) -> float | None:
49
50
  """Convert EXIF DMS (degrees/minutes/seconds) to decimal degrees."""
50
51
  try:
51
- values = dms_tag.values
52
+ values = getattr(dms_tag, "values", ())
53
+ if not values or len(values) < 3:
54
+ return None
52
55
  d = float(values[0].num) / float(values[0].den)
53
56
  m = float(values[1].num) / float(values[1].den)
54
57
  s = float(values[2].num) / float(values[2].den)
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import json
4
+ from typing import Any
4
5
 
5
6
  from sharkit.network.client import HttpClient
6
7
  from sharkit.tools.base import (
@@ -93,13 +94,13 @@ class DNSLookupTool(Tool):
93
94
 
94
95
  def _query(
95
96
  self, client: HttpClient, base_url: str, domain: str, rtype: str
96
- ) -> tuple[int, list[dict]]:
97
+ ) -> tuple[int, list[dict[str, Any]]]:
97
98
  """Query DNS and return (status, answers)."""
98
99
  url = f"{base_url}?name={domain}&type={rtype}"
99
100
  resp = client.get(url, timeout=30)
100
- data = json.loads(resp.content)
101
- status = data.get("Status", 0)
102
- answers = data.get("Answer") or []
101
+ data: dict[str, Any] = json.loads(resp.content)
102
+ status = int(data.get("Status", 0))
103
+ answers: list[dict[str, Any]] = data.get("Answer") or []
103
104
  return status, answers
104
105
 
105
106
  def execute(self, context: ExecutionContext) -> Result:
@@ -115,7 +116,7 @@ class DNSLookupTool(Tool):
115
116
  client = HttpClient(headers=headers)
116
117
 
117
118
  try:
118
- all_answers: list[dict] = []
119
+ all_answers: list[dict[str, Any]] = []
119
120
  worst_status = 0
120
121
 
121
122
  if record_type == "ALL" and provider == "cloudflare":
@@ -158,8 +159,8 @@ class DNSLookupTool(Tool):
158
159
  )
159
160
 
160
161
  # Deduplicate answers (Cloudflare ALL queries may overlap)
161
- seen: set[tuple] = set()
162
- unique: list[dict] = []
162
+ seen: set[tuple[Any, Any, Any]] = set()
163
+ unique: list[dict[str, Any]] = []
163
164
  for ans in all_answers:
164
165
  key = (ans.get("name"), ans.get("type"), ans.get("data"))
165
166
  if key not in seen:
@@ -114,7 +114,7 @@ class PortScannerTool(Tool):
114
114
  if not ports:
115
115
  return Result(success=False, error="No valid ports specified.")
116
116
 
117
- open_ports: list[dict[str, object]] = []
117
+ open_ports: list[dict[str, int | str]] = []
118
118
  for port in ports:
119
119
  try:
120
120
  sock = socket.create_connection((host, port), timeout=timeout)
@@ -132,8 +132,8 @@ class PortScannerTool(Tool):
132
132
 
133
133
  lines: list[str] = [f"Open ports on {host}:"]
134
134
  for entry in open_ports:
135
- port = entry["port"]
136
- service = entry["service"]
135
+ port = int(entry["port"])
136
+ service = str(entry["service"])
137
137
  lines.append(f" {port:<6} {service}")
138
138
 
139
139
  lines.append(f"\n{len(open_ports)} open port(s) found.")
@@ -65,32 +65,44 @@ class SSLCheckTool(Tool):
65
65
  except Exception as exc:
66
66
  return Result(success=False, error=f"SSL connection failed: {exc}")
67
67
 
68
+ if cert is None:
69
+ return Result(success=False, error=f"No certificate available for {host}:{port}.")
70
+
71
+ def _flatten_name_entries(value: object) -> dict[str, str]:
72
+ result: dict[str, str] = {}
73
+ items = value if isinstance(value, (list, tuple)) else ()
74
+ for item in items:
75
+ if not isinstance(item, (list, tuple)):
76
+ continue
77
+ for pair in item:
78
+ if not isinstance(pair, (list, tuple)) or len(pair) != 2:
79
+ continue
80
+ key, val = pair
81
+ if isinstance(key, str) and isinstance(val, str):
82
+ result[key] = val
83
+ return result
84
+
68
85
  lines: list[str] = [f"SSL Certificate for {host}:{port}:"]
69
86
  lines.append("")
70
87
 
71
- # Subject
72
- subject = dict(x[0] for x in cert.get("subject", ()))
88
+ subject = _flatten_name_entries(cert.get("subject"))
73
89
  subject_str = ", ".join(f"{k}={v}" for k, v in subject.items())
74
90
  lines.append(f" Subject: {subject_str}")
75
91
 
76
- # Issuer
77
- issuer = dict(x[0] for x in cert.get("issuer", ()))
92
+ issuer = _flatten_name_entries(cert.get("issuer"))
78
93
  issuer_str = ", ".join(f"{k}={v}" for k, v in issuer.items())
79
94
  lines.append(f" Issuer: {issuer_str}")
80
95
 
81
- # Serial number
82
- serial = cert.get("serialNumber", "?")
96
+ serial = str(cert.get("serialNumber", "?"))
83
97
  lines.append(f" Serial Number: {serial}")
84
98
 
85
- # Validity
86
- not_before = cert.get("notBefore", "?")
87
- not_after = cert.get("notAfter", "?")
99
+ not_before = str(cert.get("notBefore", "?"))
100
+ not_after = str(cert.get("notAfter", "?"))
88
101
  lines.append(f" Valid From: {not_before}")
89
102
  lines.append(f" Valid Until: {not_after}")
90
103
 
91
- # Check expiry
92
104
  try:
93
- expire_dt = datetime.datetime.strptime(not_after, "%b %d %H:%M:%S %Y %Z")
105
+ expire_dt = datetime.datetime.strptime(str(not_after), "%b %d %H:%M:%S %Y %Z")
94
106
  now = datetime.datetime.now(datetime.UTC)
95
107
  if expire_dt.replace(tzinfo=datetime.UTC) < now:
96
108
  lines.append(" Status: *** EXPIRED ***")
@@ -100,15 +112,21 @@ class SSLCheckTool(Tool):
100
112
  except ValueError:
101
113
  pass
102
114
 
103
- # SAN
104
115
  san_ext = cert.get("subjectAltName", ())
105
- if san_ext:
106
- sans = [f"{tag}={value}" for tag, value in san_ext[:10]]
107
- lines.append(f" SAN: {', '.join(sans)}")
108
- if len(san_ext) > 10:
109
- lines.append(f" ... and {len(san_ext) - 10} more")
116
+ if isinstance(san_ext, (list, tuple)):
117
+ show_san = san_ext[:10]
118
+ sans = [
119
+ f"{tag}={value}"
120
+ for entry in show_san
121
+ if isinstance(entry, (list, tuple)) and len(entry) == 2
122
+ for tag, value in [(entry[0], entry[1])]
123
+ if isinstance(tag, str) and isinstance(value, str)
124
+ ]
125
+ if sans:
126
+ lines.append(f" SAN: {', '.join(sans)}")
127
+ if len(san_ext) > 10:
128
+ lines.append(f" ... and {len(san_ext) - 10} more")
110
129
 
111
- # TLS version and cipher
112
130
  lines.append(f" TLS Version: {version}")
113
131
  if cipher:
114
132
  lines.append(f" Cipher: {cipher[0]} ({cipher[1]} bits)")
File without changes
File without changes
File without changes