jseye 1.0.2__tar.gz → 1.0.3__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 (39) hide show
  1. {jseye-1.0.2/jseye.egg-info → jseye-1.0.3}/PKG-INFO +2 -1
  2. {jseye-1.0.2 → jseye-1.0.3}/jseye/__init__.py +1 -1
  3. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/harvest.py +13 -2
  4. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/js_download.py +58 -3
  5. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/tiered_analysis.py +9 -3
  6. {jseye-1.0.2 → jseye-1.0.3/jseye.egg-info}/PKG-INFO +2 -1
  7. {jseye-1.0.2 → jseye-1.0.3}/jseye.egg-info/requires.txt +1 -0
  8. {jseye-1.0.2 → jseye-1.0.3}/pyproject.toml +3 -2
  9. {jseye-1.0.2 → jseye-1.0.3}/LICENSE +0 -0
  10. {jseye-1.0.2 → jseye-1.0.3}/MANIFEST.in +0 -0
  11. {jseye-1.0.2 → jseye-1.0.3}/README.md +0 -0
  12. {jseye-1.0.2 → jseye-1.0.3}/jseye/__main__.py +0 -0
  13. {jseye-1.0.2 → jseye-1.0.3}/jseye/banner.py +0 -0
  14. {jseye-1.0.2 → jseye-1.0.3}/jseye/cli.py +0 -0
  15. {jseye-1.0.2 → jseye-1.0.3}/jseye/data/regex.yaml +0 -0
  16. {jseye-1.0.2 → jseye-1.0.3}/jseye/data/vendor_blacklist.txt +0 -0
  17. {jseye-1.0.2 → jseye-1.0.3}/jseye/installer.py +0 -0
  18. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/__init__.py +0 -0
  19. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/analyze_ast.py +0 -0
  20. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/analyze_regex.py +0 -0
  21. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/correlate.py +0 -0
  22. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/js_filter.py +0 -0
  23. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/linkfinder.py +0 -0
  24. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/secrets.py +0 -0
  25. {jseye-1.0.2 → jseye-1.0.3}/jseye/modules/sinks.py +0 -0
  26. {jseye-1.0.2 → jseye-1.0.3}/jseye/pipeline.py +0 -0
  27. {jseye-1.0.2 → jseye-1.0.3}/jseye/utils/__init__.py +0 -0
  28. {jseye-1.0.2 → jseye-1.0.3}/jseye/utils/cache.py +0 -0
  29. {jseye-1.0.2 → jseye-1.0.3}/jseye/utils/fs.py +0 -0
  30. {jseye-1.0.2 → jseye-1.0.3}/jseye/utils/hashing.py +0 -0
  31. {jseye-1.0.2 → jseye-1.0.3}/jseye/utils/logger.py +0 -0
  32. {jseye-1.0.2 → jseye-1.0.3}/jseye/utils/shell.py +0 -0
  33. {jseye-1.0.2 → jseye-1.0.3}/jseye.egg-info/SOURCES.txt +0 -0
  34. {jseye-1.0.2 → jseye-1.0.3}/jseye.egg-info/dependency_links.txt +0 -0
  35. {jseye-1.0.2 → jseye-1.0.3}/jseye.egg-info/entry_points.txt +0 -0
  36. {jseye-1.0.2 → jseye-1.0.3}/jseye.egg-info/top_level.txt +0 -0
  37. {jseye-1.0.2 → jseye-1.0.3}/scripts/ast_parser.js +0 -0
  38. {jseye-1.0.2 → jseye-1.0.3}/setup.cfg +0 -0
  39. {jseye-1.0.2 → jseye-1.0.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jseye
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: JavaScript Intelligence & Attack Surface Discovery Tool
5
5
  Home-page: https://github.com/letchupkt/jseye
6
6
  Author: Lakshmikanthan K
@@ -32,6 +32,7 @@ Requires-Dist: pyyaml>=6.0
32
32
  Requires-Dist: requests>=2.28.0
33
33
  Requires-Dist: urllib3>=1.26.0
34
34
  Requires-Dist: jsbeautifier>=1.14.0
35
+ Requires-Dist: aiohttp>=3.8.0
35
36
  Provides-Extra: dev
36
37
  Requires-Dist: pytest>=7.0.0; extra == "dev"
37
38
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
@@ -4,6 +4,6 @@ Author: Lakshmikanthan K (letchupkt)
4
4
  License: MIT
5
5
  """
6
6
 
7
- __version__ = "1.0.2"
7
+ __version__ = "1.0.3"
8
8
  __author__ = "Lakshmikanthan K (letchupkt)"
9
9
  __email__ = "letchupkt.dev@gmail.com"
@@ -17,10 +17,12 @@ console = Console()
17
17
  class URLHarvester:
18
18
  """Harvest URLs from multiple sources in parallel"""
19
19
 
20
- def __init__(self, output_dir: Path):
20
+ def __init__(self, output_dir: Path, cache_manager=None):
21
21
  self.output_dir = output_dir
22
+ self.cache_manager = cache_manager
22
23
  self.deduplicator = DeduplicatorHash()
23
24
  self.timeout = 120 # 2 minutes per tool
25
+ self.performance_stats = {}
24
26
 
25
27
  async def run_tool_async(self, tool_name: str, domain: str) -> List[str]:
26
28
  """Run a single tool asynchronously"""
@@ -174,4 +176,13 @@ class URLHarvester:
174
176
  except Exception as e:
175
177
  log_progress(f"{tool_name} failed for {domain}: {e}")
176
178
 
177
- return self.deduplicator.deduplicate_list(all_urls)
179
+ return self.deduplicator.deduplicate_list(all_urls)
180
+
181
+
182
+ def get_performance_stats(self) -> Dict:
183
+ """Get performance statistics"""
184
+ return self.performance_stats
185
+
186
+ def harvest_urls_parallel(self, domains: List[str]) -> List[str]:
187
+ """Alias for harvest_urls for backward compatibility"""
188
+ return self.harvest_urls(domains)
@@ -18,13 +18,13 @@ from ..utils.cache import JSEyeCache
18
18
  class JSDownloader:
19
19
  """Download JavaScript files with caching and parallel processing"""
20
20
 
21
- def __init__(self, output_dir: Path):
21
+ def __init__(self, output_dir: Path, cache_manager=None):
22
22
  self.output_dir = output_dir
23
23
  self.js_dir = output_dir / "js_files"
24
24
  ensure_dir(self.js_dir)
25
25
 
26
26
  # Initialize cache
27
- self.cache = JSEyeCache(output_dir)
27
+ self.cache = cache_manager if cache_manager else JSEyeCache(output_dir)
28
28
 
29
29
  # Download settings
30
30
  self.max_file_size = 3 * 1024 * 1024 # 3MB limit
@@ -34,6 +34,8 @@ class JSDownloader:
34
34
  self.session_headers = {
35
35
  'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
36
36
  }
37
+
38
+ self.performance_stats = {}
37
39
 
38
40
  async def download_js_file_async(self, session: aiohttp.ClientSession, url: str) -> Dict:
39
41
  """Download a single JavaScript file asynchronously with caching"""
@@ -275,4 +277,57 @@ class JSDownloader:
275
277
  successful = len([r for r in results if r['status'] == 'success'])
276
278
  log_progress(f"Sequential download complete: {successful}/{len(urls)} successful")
277
279
 
278
- return results
280
+ return results
281
+
282
+
283
+ def get_performance_stats(self) -> Dict:
284
+ """Get performance statistics"""
285
+ return self.performance_stats
286
+
287
+ def download_js_files_parallel(self, urls: List[str], max_files: int = 200) -> List[Dict]:
288
+ """Alias for async download - backward compatibility"""
289
+ urls_to_download = urls[:max_files]
290
+ return asyncio.run(self.download_js_files_async(urls_to_download))
291
+
292
+ async def download_js_files_async(self, urls: List[str]) -> List[Dict]:
293
+ """Async wrapper for download_js_files_parallel"""
294
+ return await self.download_js_files_parallel_internal(urls)
295
+
296
+ async def download_js_files_parallel_internal(self, urls: List[str]) -> List[Dict]:
297
+ """Internal parallel download method"""
298
+ log_progress(f">> Downloading {len(urls)} JavaScript files in parallel...")
299
+
300
+ # Create semaphore to limit concurrent downloads
301
+ semaphore = asyncio.Semaphore(self.max_concurrent)
302
+
303
+ async def download_with_semaphore(url):
304
+ async with semaphore:
305
+ async with aiohttp.ClientSession(headers=self.session_headers) as session:
306
+ return await self.download_js_file_async(session, url)
307
+
308
+ # Download all files in parallel
309
+ tasks = [download_with_semaphore(url) for url in urls]
310
+ results = await asyncio.gather(*tasks, return_exceptions=True)
311
+
312
+ # Filter out exceptions
313
+ valid_results = []
314
+ for i, result in enumerate(results):
315
+ if isinstance(result, Exception):
316
+ log_progress(f"Download exception for {urls[i]}: {result}")
317
+ valid_results.append({
318
+ 'url': urls[i],
319
+ 'filepath': None,
320
+ 'size': 0,
321
+ 'status': 'exception',
322
+ 'error': str(result)
323
+ })
324
+ else:
325
+ valid_results.append(result)
326
+
327
+ # Count successful downloads
328
+ successful = len([r for r in valid_results if r['status'] == 'success'])
329
+ cached = len([r for r in valid_results if 'cached_at' in r])
330
+
331
+ log_progress(f"[C] Download complete: {successful} new, {cached} cached, {len(valid_results)} total")
332
+
333
+ return valid_results
@@ -17,15 +17,16 @@ from .secrets import SecretsDetector
17
17
 
18
18
  class TieredAnalysisEngine:
19
19
  """
20
- 🔥 TIERED ANALYSIS MODEL
20
+ >> TIERED ANALYSIS MODEL
21
21
 
22
22
  Tier 1: Regex + AST + LinkFinder + Secrets (HEAVY) - Top 20%
23
23
  Tier 2: Regex + LinkFinder (MEDIUM) - Next 30%
24
24
  Tier 3: Regex only (FAST) - Remaining 50%
25
25
  """
26
26
 
27
- def __init__(self, output_dir: Path):
27
+ def __init__(self, output_dir: Path, cache_manager=None):
28
28
  self.output_dir = output_dir
29
+ self.cache_manager = cache_manager
29
30
  self.regex_analyzer = RegexAnalyzer(output_dir)
30
31
  self.ast_analyzer = ASTAnalyzer(output_dir)
31
32
  self.linkfinder = LinkFinderIntegration(output_dir)
@@ -301,4 +302,9 @@ class TieredAnalysisEngine:
301
302
  'secrets': secrets,
302
303
  'sinks': sinks,
303
304
  'functions': functions
304
- }
305
+ }
306
+
307
+
308
+ def get_performance_stats(self) -> Dict:
309
+ """Get performance statistics"""
310
+ return self.analysis_stats
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jseye
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: JavaScript Intelligence & Attack Surface Discovery Tool
5
5
  Home-page: https://github.com/letchupkt/jseye
6
6
  Author: Lakshmikanthan K
@@ -32,6 +32,7 @@ Requires-Dist: pyyaml>=6.0
32
32
  Requires-Dist: requests>=2.28.0
33
33
  Requires-Dist: urllib3>=1.26.0
34
34
  Requires-Dist: jsbeautifier>=1.14.0
35
+ Requires-Dist: aiohttp>=3.8.0
35
36
  Provides-Extra: dev
36
37
  Requires-Dist: pytest>=7.0.0; extra == "dev"
37
38
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
@@ -3,6 +3,7 @@ pyyaml>=6.0
3
3
  requests>=2.28.0
4
4
  urllib3>=1.26.0
5
5
  jsbeautifier>=1.14.0
6
+ aiohttp>=3.8.0
6
7
 
7
8
  [dev]
8
9
  pytest>=7.0.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jseye"
7
- version = "1.0.2"
7
+ version = "1.0.3"
8
8
  description = "JavaScript Intelligence & Attack Surface Discovery Tool"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -35,7 +35,8 @@ dependencies = [
35
35
  "pyyaml>=6.0",
36
36
  "requests>=2.28.0",
37
37
  "urllib3>=1.26.0",
38
- "jsbeautifier>=1.14.0"
38
+ "jsbeautifier>=1.14.0",
39
+ "aiohttp>=3.8.0"
39
40
  ]
40
41
 
41
42
  [project.optional-dependencies]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes