Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

fix(basket): redact sensitive params and keep query separators in batched outgoing link hrefs

Open Beginner friendly
#1,143 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@ANSHSINGH050404 is already working on this.

Since Oct 19, 2026.

  • #1144 by @ANSHSINGH050404 — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
84/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
bun, typescript
Domain
backend

Research direction

Read apps/basket/src/routes/basket.ts around processOutgoingLinkData and compare its href handling with apps/basket/src/lib/event-service.ts around insertOutgoingLink. Start with the validation utilities in apps/basket/src/utils/validation.ts; the issue proposes using sanitizeUrl for the batch href. Done means batch links preserve query separators and redact sensitive query values like the single-event path.

Written by the indexing model from the issue text.

Description

Problem

POST /batch stores outgoing-link href values with a different sanitizer than every other outgoing-link write path. POST / and GET /px.jpg use sanitizeUrl; the batch path uses sanitizeString.

The two differ in two ways that matter:

  1. sanitizeString strips & (it removes < > ' " &), so query parameters fuse together: ?utm_source=x&plan=pro is stored as ?utm_source=xplan=pro. The recorded outgoing-link destination is wrong and per-parameter attribution breaks.
  2. sanitizeString does not redact sensitive query parameters, so token, email, password, api_key, otp, credit_card and the other keys in SENSITIVE_QUERY_PARAMS are written verbatim into analytics.outgoing_links.href. The single-event path stores REDACTED for the same payload.
POST /batch  ->  https://partner.example/click?a=1b=2token=secret
POST /       ->  https://partner.example/click?a=1&b=2&token=REDACTED

This is the same defect class fixed for the other paths in #1135 ("keep & in sanitized URLs so query parameters stay separate") and #1136 ("redact sensitive params in hash-routed URL fragments"); the batch path was left behind.

Root cause

apps/basket/src/routes/basket.ts:144 (processOutgoingLinkData) calls sanitizeString(linkData.href, ...). apps/basket/src/lib/event-service.ts:365 (insertOutgoingLink, used by POST / and GET /px.jpg) calls sanitizeUrl(linkData.href, ...).

In apps/basket/src/utils/validation.ts:

  • sanitizeString uses UNSAFE_CHARS_REGEX = /[<>'"&]/g — strips &, no redaction.
  • sanitizeUrl uses URL_UNSAFE_CHARS_REGEX = /[<>'"]/g — preserves &, and applies redactSensitiveQueryParams first.

Every other URL-bearing field in the service — track referrer/url/path, vitals, errors, custom events, engagement spans, blocked traffic — already uses sanitizeUrl. The batch outgoing-link href is the only divergence.

To reproduce

bun -e "const {sanitizeString, sanitizeUrl} = await import('./apps/basket/src/utils/validation.ts');
const h='https://partner.example/click?a=1&b=2&token=secret&[email protected]';
console.log('batch (sanitizeString):', sanitizeString(h,2048));
console.log('single(sanitizeUrl)   :', sanitizeUrl(h,2048));"
batch (sanitizeString): https://partner.example/[email protected]
single(sanitizeUrl)   : https://partner.example/click?a=1&b=2&token=REDACTED&email=REDACTED

At the route level, POST /batch with a body of:

[
  {
    "type": "outgoing_link",
    "eventId": "evt_link_1",
    "href": "https://partner.example/click?a=1&b=2&token=secret",
    "text": "Partner"
  }
]

stores href = "https://partner.example/click?a=1b=2token=secret", while the identical payload on POST / stores "https://partner.example/click?a=1&b=2&token=REDACTED".

Proposed fix

Use sanitizeUrl for the batch outgoing-link href, matching every other outgoing-link write path:

-			href: sanitizeString(linkData.href, VALIDATION_LIMITS.PATH_MAX_LENGTH),
+			href: sanitizeUrl(linkData.href, VALIDATION_LIMITS.PATH_MAX_LENGTH),

No new abstraction and no behavior change to any other field.

Scope note

The first-party browser tracker posts outgoing links to POST / (packages/tracker/src/plugins/outgoing-links.ts:37), so the shipped tracker is unaffected today. The defect hits direct POST /batch consumers — the endpoint's own public surface — and would silently widen if any SDK path starts batching outgoing links.

Rows already written stay as they are. No migration is proposed, since analytics.outgoing_links is an append-only analytics table.

AI usage disclosure

I used OpenCode

Dominant language
TypeScript
Stars
1.2k
Forks
227
Avg merge
23h 41m
Merged PRs (30d)
250

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from databuddy-analytics/Databuddy

All issues in databuddy-analytics/Databuddy

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.