Date: 2026-02-18
Repo: /workspace/bounties/marketplace-service-template
Scope:
src/routes/research.tssrc/routes/trending.tssrc/scrapers/reddit.tssrc/scrapers/web.tssrc/analysis/patterns.tssrc/analysis/sentiment.ts
researchaccepted unbounded topic/body size and loose platform validation.trendingaccepted unboundedplatformsquery length and weak platform filtering.- scraper entry points accepted weak/unbounded input values.
- Route-level limit existed globally, but no endpoint-specific guard on higher-cost Trend Intelligence endpoints.
- Potential header injection risk when echoing
payment.txHashinto response headers.
- Parsing logic in web and analysis layers could process overly large payloads and term sets.
- RSS article extraction had no per-topic cap.
- Pattern extraction could grow maps with excessive keywords.
- Core scraper requests already had timeout support through
proxyFetch, but not all pathways reused the same hardened flow. - Needed stronger body-size checks and parse guards on fetched content.
- Added endpoint-specific in-memory rate limiter for
/api/research:- default
12 req/minper client IP - configurable via
RESEARCH_RATE_LIMIT_PER_MIN
- default
- Added strict request checks:
Content-Typevalidation (application/json)- max body size
8KB(413on overflow) - JSON object-only body validation
- bounded
topicvalidation (2..200 chars, control chars blocked) - validated
platformsas supported set only - bounded numeric
daysparsing - country normalization to strict ISO-2 fallback
- Switched proxy exit IP lookup to hardened
proxyFetchpath with timeout and retry controls. - Added payment verification error handling when verifier is unavailable.
- Sanitized
X-Payment-TxHashresponse header value. - Added defensive truncation before sentiment aggregation.
- Added endpoint-specific in-memory rate limiter for
/api/trending:- default
30 req/minper client IP - configurable via
TRENDING_RATE_LIMIT_PER_MIN
- default
- Added strict query parsing and validation:
countrynormalized to strict ISO-2 fallbackplatformsquery max length check and allowlist filtering- deduped requested platforms
- bounded
limit(1..50)
- Switched proxy exit IP lookup to hardened
proxyFetchpath. - Added payment verifier availability handling.
- Sanitized
X-Payment-TxHashresponse header value.
- Added input bounds and sanitization for:
- topic length
- subreddit format (
^[A-Za-z0-9_]{2,21}$) - days and limit clamping
- Added safe mapping and normalization:
- text cleanup
- URL normalization to
http/httpsonly - numeric clamping for score/comment/upvote ratio
- Added defensive JSON parsing with explicit error messages.
- Ensured all proxy requests keep timeout + retry settings.
- Added strict bounds:
- topic length, limit, title/snippet/source/url lengths
- max articles per trend item (
5)
- Added URL normalization to allow only
http/httpsURLs in parsed output. - Added upstream payload size checks before processing:
- DDG max
1.5MB - Trends RSS max
1MB
- DDG max
- Added response body read guard (
arrayBuffer) with explicit size enforcement. - Kept timeout and retry settings on all external calls.
- Added bounded processing controls:
- max items per platform
- max text length, token count, terms per text
- max keyword map size per platform
- max merged signal keyword count
- Added keyword normalization and allowlist checks.
- Deduped per-document terms to reduce amplification/noise.
- Bounded top keyword output size for helper method.
- Added bounded processing controls:
- max text length per input
- max tokens per text
- max texts per aggregate batch
- Added text sanitization before tokenization.
- Added stronger guard behavior for empty/invalid input arrays.
- No direct user-supplied outbound URL fetch path was present in this scope.
- Scrapers fetch only fixed upstream domains:
reddit.comhtml.duckduckgo.comtrends.google.comapi.ipify.org
- Parsed URLs are now normalized to
http/httpsonly before returning. - Added stricter payload size and parsing limits to reduce parser abuse risk.
Executed:
bun run typecheckResult: pass.
Executed:
bun testResult: no tests found in repo (bun exited with code 1).
- Changes were kept practical and low-risk.
- No architectural rewrites were introduced.