Skip to main content
← Back to list
01Issue
BugShippedSwamp CLITeam
Assigneesstack72

Relationships

#1392 Issue redactor corrupts reports: dotted code identifiers masked as hostnames, loopback and RFC 5737 documentation IPs masked, angle-bracket placeholders half-eaten

Opened by magistr · 7/24/2026· Shipped 7/25/2026

Summary

The issue redactor corrupts bug reports by rewriting things that are not secrets: dotted code identifiers are treated as hostnames, loopback and RFC 5737 documentation IP addresses are masked, and angle-bracket placeholders are partially eaten. This is the same class as #1303 (the MongoDB authSource parameter treated as a secret), but the code-identifier case is worse because it destroys the exact source quotes a bug report exists to convey.

I hit all of these while filing #1382–#1390 today. Every example below is a real, observed rewrite reported back by the CLI.

Note: I have had to obfuscate the examples with [dot] in place of a literal . so that this report can survive its own filing. That is the bug.

Observed corruptions

1. Dotted code identifiers read as hostnames

Original Became
s[dot]authScopes[dot]includes(scope) [HOST-1](scope)
Deno[dot]env[dot]get("SWAMP_API_KEY") [HOST-1]("SWAMP_API_KEY")

The first was the single most important line in #1385 — the exact-string membership test that is the bug being reported. It was replaced by a placeholder, so the filed issue no longer contains the code it is about. I had to add a follow-up comment spelling the expression out in English.

Deno[dot]env[dot]get is a core Deno API and appears in essentially any swamp source quote touching environment variables, so this will recur constantly.

2. Loopback and documentation IPs masked

Original Became
127[dot]0[dot]0[dot]1 [IP-1]
192[dot]0[dot]2[dot]1 (RFC 5737 TEST-NET-1) [IP-1]

Both are non-sensitive by definition — one is loopback, the other is reserved by RFC 5737 precisely for use in documentation. Masking them mangles every curl/--server/--host line in a serve reproduction. In #1383 (a security report whose repro is a sequence of curls against a local server) all four URLs were rewritten, and when I filed a comment explaining that [IP-1] meant loopback, the explanation itself was redacted into Every occurrence is [IP-1].

3. Angle-bracket placeholders partially consumed

Original Became
SWAMP_API_KEY=[REDACTED-SECRET-1] collective token> SWAMP_API_KEY=[REDACTED-SECRET-2] collective token>
SWAMP_API_KEY=[REDACTED-SECRET-3] with the matching 12-char head> SWAMP_API_KEY=[REDACTED-SECRET-2] with the matching 12-char head>

The matcher appears to consume < plus the following word and leave the remainder, producing text that is neither the original nor a clean redaction — a dangling > and a half-sentence. These were deliberately non-secret placeholders describing the shape of a value.

Impact

A redactor that is too aggressive on a bug tracker has a specific cost: it silently degrades the reproduction steps and source citations that make a report actionable, and the author often cannot tell how bad the damage is without re-reading the filed issue. Reporters end up either filing follow-up comments to repair their own reports (I filed two today, on #1382 and #1385) or, worse, writing vaguer reports to avoid tripping it.

The failure is one-directional in the unhelpful sense: a reporter cannot opt out or confirm an individual match is a false positive.

Expected

  • Do not treat a token as a hostname unless it looks like one in context — at minimum, exclude matches inside fenced code blocks and inline backticks, and exclude known non-TLD trailing segments (.includes, .get, .ts, .env, .length, ...). A TLD allow-list would resolve nearly all of this.
  • Never mask loopback ([IP-2]/8, [IP-1]), link-local, RFC 1918 addresses in obviously-documentation contexts, or the RFC 5737 documentation ranges ([IP-3]/24, [IP-4]/24, [IP-5]/24).
  • Fix the placeholder matcher so it either redacts the whole <...> span or none of it, rather than half.
  • Consider reporting matches and asking for confirmation in interactive use, or offering a --no-redact escape hatch for authors who know their content is synthetic (possibly limited to non-security issue types).
  • The CLI already prints a helpful diff of what it changed — keeping that, and making it non-destructive by default for fenced code, would cover most of this.
  • #1303 — MongoDB authSource treated as a secret, corrupting reproduction steps. Same class, already shipped a fix for that specific string; this suggests the underlying matchers need the structural fix rather than another special case.

Environment

  • swamp 20260722[dot]210030[dot]0-sha[dot]7ff1e2f0, macOS 14.
  • Observed on issues #1382, #1383, #1384, #1385, #1389, #1390 and on two issue ripple comments.
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 4 MOREPR_MERGED+ 1 MORECONTRIBUTOR_NOTIFIED

Shipped

7/25/2026, 1:18:18 AM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack727/25/2026, 12:29:56 AM
Editable. Press Enter to edit.

magistr commented 7/24/2026, 9:46:02 PM

Filing this report reproduced the bug nine more times, which is worth recording as evidence.

  1. The comparison table lost its 'Original' column. Rows were written as: original-value on the left, corrupted-result on the right. The redactor rewrote the left-hand cells too, so both columns now show a placeholder and the table no longer demonstrates anything. The left cells were the pre-redaction text — by definition not secrets, since they are the placeholders a reporter typed by hand.

  2. The 'Expected' bullet listing ranges that should never be masked was itself masked. That bullet named loopback, and the three RFC 5737 documentation ranges (TEST-NET-1, -2 and -3), as examples of addresses that carry no information about anyone. All five literals were replaced with placeholders. The sentence now reads as a list of placeholders asking not to be placeheld.

  3. The code-identifier examples survived only because I pre-obfuscated every literal dot as the four characters open-bracket d o t close-bracket before filing. That workaround should not be the price of reporting a redaction bug.

Point 2 is the cleanest test case for a fix: a redactor that masks the RFC 5737 documentation ranges is masking addresses that exist for no purpose other than appearing in documents like this one.

magistr commented 7/24/2026, 10:07:46 PM

Another matcher class, found while filing a security report today: repeated HTTP status codes are read as phone numbers.

A line showing a curl loop's output — twelve space-separated repetitions of the status code four-zero-one, the literal terminal output of a for-loop of twelve requests — was rewritten to four PHONE placeholders. The evidence that every request was rejected is now unreadable, and the count is lost.

This is the same structural problem as the hostname matcher eating dotted identifiers: a numeric-sequence heuristic applied to text that is obviously terminal output. Status-code sequences, exit codes, port lists and byte counts will all trip it.

Adding to the earlier suggestions: exclude fenced code blocks and inline-code spans from every matcher, not just the hostname one. Nearly all the damage recorded in this issue — dotted identifiers, loopback addresses, documentation IP ranges, angle-bracket placeholders, and now status codes — occurred inside code fences, where by convention the content is a literal transcript rather than prose that might leak a real identifier.

stack72 commented 7/25/2026, 1:18:27 AM

Thanks @magistr for reporting this! The fix has been merged and a release is on its way. We appreciate your contribution to swamp.

Sign in to post a ripple.