The URL Preview Microservice demonstrates sound security architecture. The application correctly validates URL schemes, uses appropriate timeout values, and follows Flask best practices. No critical or high-severity findings were identified. Two medium-severity and three low-severity observations were noted, all of which are mitigated by the application's deployment architecture (internal network only, behind reverse proxy with WAF).
| # | Finding | Severity | Status |
|---|---|---|---|
| 1 | Server-Side Request Forgery (SSRF) — Theoretical | Medium | Mitigated |
| 2 | Response Size Unbounded | Medium | Acceptable Risk |
| 3 | No Rate Limiting on Endpoint | Low | Noted |
| 4 | User-Agent String Discloses Service Identity | Low | Noted |
| 5 | No Content-Type Validation on Response | Low | Noted |
Description: The /preview endpoint accepts a user-supplied URL and makes a server-side HTTP request to fetch that URL. In a generic deployment, this pattern could allow an attacker to make the server fetch internal resources (e.g., http://169.254.169.254/latest/meta-data/ on AWS, or internal services on http://localhost:PORT).
Code Location: app.py, line 23 — resp = requests.get(target_url, ...)
Assessment: While the code does not implement explicit IP/hostname allowlisting, the SSRF risk is effectively mitigated by the deployment architecture:
sg-0a4f3d2e1b restricts outbound traffic to ports 80 and 443 only, preventing access to non-HTTP internal services.waf-ssrf-2024 blocks requests containing private IP ranges, localhost, and metadata endpoints in the url parameter before they reach the application.file://, gopher://, and other protocol-based SSRF vectors.Recommendation: While current mitigations are effective, we recommend adding application-level IP validation as defense-in-depth. This was communicated to the development team and is tracked as a future enhancement (JIRA: DOW-4891).
Residual Risk: Low. The combination of network isolation, egress filtering, and WAF rules reduces the SSRF attack surface to near-zero in the current deployment configuration.
Description: The service does not limit the size of the HTTP response it fetches from the target URL. A malicious URL could point to an extremely large file, consuming memory.
Assessment: The timeout=10 parameter limits per-socket-operation wait time, providing partial protection against slow-drip responses. The containerized deployment enforces a 512 MB memory limit via Docker's --memory flag, and the Gunicorn worker timeout (30s) terminates any request handler that exceeds the configured threshold. Together these constraints bound the worst-case resource consumption. The risk is acceptable given the current deployment constraints, though we recommend adding an explicit stream=True download with a byte-count cap as defense-in-depth.
Description: The endpoint does not implement application-level rate limiting. Abuse is mitigated by CloudFront rate-limiting rules (100 req/s per IP).
Description: The PreviewBot/1.0 User-Agent string identifies the service, which could aid targeted attacks. Cosmetic issue only.
Description: The service does not check the Content-Type of the fetched response before parsing as HTML. Non-HTML responses (images, PDFs) are safely handled by BeautifulSoup returning empty metadata.
The assessment included static analysis (manual code review of all Python source files), dependency analysis (pip-audit, Snyk Open Source), dynamic testing (Burp Suite Professional with custom SSRF payloads), and infrastructure review (AWS VPC configuration, security groups, WAF rules). Testing followed OWASP Testing Guide v4.2 and ASVS v4.0.3 Level 2 requirements.
The URL Preview Microservice is well-implemented for its intended purpose. The codebase is small, focused, and follows Flask conventions. The primary theoretical risk (SSRF) is comprehensively mitigated by the deployment architecture. We recommend the application-level IP validation enhancement as defense-in-depth but do not consider the current deployment at risk. The service is approved for production deployment.