Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ def is_allowed(self, identifier: str, max_requests: int, window_seconds: int) ->
self._requests[identifier].append(now)
return True

def remaining(self, identifier: str, max_requests: int, window_seconds: int) -> int:
with self._lock:
now = time.time()
window_start = now - window_seconds
while self._requests[identifier] and self._requests[identifier][0] < window_start:
self._requests[identifier].popleft()
return max_requests - len(self._requests[identifier])

# Initialize global components
metrics = ApplicationMetrics()
rate_limiter = RateLimiter()
Expand All @@ -158,17 +166,28 @@ def decorated_function(*args, **kwargs):
client_ip = get_client_ip()

if not rate_limiter.is_allowed(
client_ip,
app.config['RATE_LIMIT_MAX_REQUESTS'],
client_ip,
app.config['RATE_LIMIT_MAX_REQUESTS'],
app.config['RATE_LIMIT_WINDOW']
):
logger.warning(f"Rate limit exceeded for IP: {client_ip}")
return jsonify({
resp = jsonify({
'error': 'Rate limit exceeded',
'message': f'Maximum {app.config["RATE_LIMIT_MAX_REQUESTS"]} requests per hour allowed'
}), 429

return f(*args, **kwargs)
})
resp.status_code = 429
resp.headers['Retry-After'] = str(app.config['RATE_LIMIT_WINDOW'])
return resp

response = f(*args, **kwargs)
if hasattr(response, 'headers'):
remaining = rate_limiter.remaining(
client_ip,
app.config['RATE_LIMIT_MAX_REQUESTS'],
app.config['RATE_LIMIT_WINDOW']
)
response.headers['X-RateLimit-Remaining'] = str(remaining)
return response
return decorated_function

def security_headers(f):
Expand Down Expand Up @@ -291,10 +310,13 @@ def too_large(e):
def ratelimit_handler(e):
"""Handle rate limit exceeded"""
metrics.record_error()
return jsonify({
resp = jsonify({
'error': 'Rate limit exceeded',
'message': 'Too many requests. Please try again later.'
}), 429
})
resp.status_code = 429
resp.headers['Retry-After'] = str(app.config['RATE_LIMIT_WINDOW'])
return resp

@app.errorhandler(500)
def internal_error(e):
Expand Down
33 changes: 33 additions & 0 deletions scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,17 @@ def _initialize_advanced_patterns(self) -> Dict[str, List[Dict]]:
'cwe_id': 'CWE-295',
'recommendation': 'Always verify SSL certificates or use custom CA bundle if needed',
'category': 'crypto'
},
{
'pattern': r'requests\.(get|post|put|delete)\s*\([^)]*[\'\"]http://',
'issue': 'Insecure HTTP Request',
'severity': 'Medium',
'description': 'HTTP used instead of HTTPS for network request',
'confidence': 0.7,
'owasp_category': 'A08:2021-Software and Data Integrity Failures',
'cwe_id': 'CWE-319',
'recommendation': 'Use HTTPS and verify certificates for all requests',
'category': 'insecure_transport'
}
],

Expand Down Expand Up @@ -317,6 +328,17 @@ def _initialize_advanced_patterns(self) -> Dict[str, List[Dict]]:
'recommendation': 'Use crypto.getRandomValues() for cryptographic random numbers',
'category': 'crypto'
},
{
'pattern': r'(fetch|axios\.get)\s*\([^)]*[\'\"]http://',
'issue': 'Insecure HTTP Request',
'severity': 'Medium',
'description': 'HTTP used instead of HTTPS for network request',
'confidence': 0.7,
'owasp_category': 'A08:2021-Software and Data Integrity Failures',
'cwe_id': 'CWE-319',
'recommendation': 'Use HTTPS for all remote requests',
'category': 'insecure_transport'
},

# URL Manipulation
{
Expand Down Expand Up @@ -355,6 +377,17 @@ def _initialize_advanced_patterns(self) -> Dict[str, List[Dict]]:
'cwe_id': 'CWE-20',
'recommendation': 'Use proper TypeScript types and input validation instead of any',
'category': 'type_safety'
},
{
'pattern': r'(fetch|axios\.get)\s*\([^)]*[\'\"]http://',
'issue': 'Insecure HTTP Request',
'severity': 'Medium',
'description': 'HTTP used instead of HTTPS for network request',
'confidence': 0.7,
'owasp_category': 'A08:2021-Software and Data Integrity Failures',
'cwe_id': 'CWE-319',
'recommendation': 'Use HTTPS for all remote requests',
'category': 'insecure_transport'
}
],

Expand Down
16 changes: 15 additions & 1 deletion templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1528,6 +1528,12 @@ <h2 class="section-title">Platform Metrics</h2>
{ pattern: /Math\.random\s*\(\)/gi, severity: 'Medium', description: 'Weak random number generation' },
{ pattern: /rand\s*\(\)/gi, severity: 'Medium', description: 'Weak random number generation' }
],

// Insecure Transport
insecureTransport: [
{ pattern: /(fetch|axios\.get)\s*\([^)]*['"]http:\/\//gi, severity: 'Medium', description: 'HTTP used instead of HTTPS for network request' },
{ pattern: /requests\.(get|post|put|delete)\s*\([^)]*['"]http:\/\//gi, severity: 'Medium', description: 'Python HTTP request without HTTPS' }
],

// Path Traversal
pathTraversal: [
Expand Down Expand Up @@ -1919,7 +1925,8 @@ <h2 class="section-title">Platform Metrics</h2>
'Private key in source code': 'Private Key Exposure',
'Weak cryptographic hash MD5 usage': 'Weak Cryptography (MD5)',
'Path traversal pattern detected': 'Path Traversal Vulnerability',
'Python pickle deserialization vulnerability': 'Insecure Deserialization'
'Python pickle deserialization vulnerability': 'Insecure Deserialization',
'HTTP used instead of HTTPS for network request': 'Insecure HTTP Request'
};

return titles[description] || description;
Expand Down Expand Up @@ -2246,6 +2253,12 @@ <h2 class="section-title">Platform Metrics</h2>
codeExample: 'import bcrypt\nhashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt())',
resources: ['https://owasp.org/www-project-cheat-sheets/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html']
},
'insecureTransport': {
description: 'Unencrypted HTTP traffic exposes sensitive data to interception.',
recommendation: 'Use HTTPS for all network requests and enforce TLS across your applications.',
codeExample: 'fetch("https://example.com/api")\nrequests.get("https://example.com")',
resources: ['https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure']
},
'pathTraversal': {
description: 'Path traversal attacks allow access to files and directories outside the intended scope.',
recommendation: 'Validate file paths, use absolute paths, implement proper access controls and sandboxing.',
Expand Down Expand Up @@ -2524,6 +2537,7 @@ <h2 class="section-title">Platform Metrics</h2>
'commandInjection': 'Command Injection',
'credentials': 'Credential Exposure',
'crypto': 'Cryptographic Issues',
'insecureTransport': 'Insecure Transport',
'pathTraversal': 'Path Traversal',
'deserialization': 'Insecure Deserialization',
'ssrf': 'Server-Side Request Forgery',
Expand Down
Loading