changelog: clean GitHub URL paths before the private-repo check (Astra round 3)
github.com/carlosframework/public/../platform.git now fails.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 files changed,
+17
−2
docs/superpowers/specs/CODEX-FINDINGS-CHANGELOG-CODE-3.md+11 −0internal/changelog/build.go+5 −2internal/changelog/build_test.go+1 −0
CI passed — run details
diff --git a/docs/superpowers/specs/CODEX-FINDINGS-CHANGELOG-CODE-3.md b/docs/superpowers/specs/CODEX-FINDINGS-CHANGELOG-CODE-3.md| new file mode 100644 |
| index 000000000..906dffe77 |
| --- /dev/null |
| +++ b/docs/superpowers/specs/CODEX-FINDINGS-CHANGELOG-CODE-3.md |
| @@ -0,0 +1,11 @@ |
| +| Previous finding | Disposition | Evidence | |
| +|---|---|---| |
| +| **1. P1 — Encoded addresses and private links bypass validation** | **Not fully fixed** | `[source](https://github.com/carlosframework/public/../platform.git)` still passes the website checker when rendered in memory. The browser normalizes its destination to the private repository’s clone URL. [Go normalization](/home/paulca/amadan.net/carlos/platform-changelog/internal/changelog/build.go:634) removes `/./` but leaves `/../`, so its private-repository pattern misses this input. The [website pattern](/home/paulca/github.com/carlosframework/website-changelog/hack/check-docs.mjs:151) checks the normalized path but misses the `.git` suffix. **Remaining fix:** normalize complete URL paths in Go and recognize optional `.git` repository suffixes in both validators; add this regression case. | |
| + |
| +No new P1 or P2 findings. This remaining bypass belongs to finding 1. |
| + |
| +Correction to round 2: `ops**@**example.org` renders literally. The valid split-address example `**ops@example**.org` is now rejected, as is the original `/./platform` URL. |
| + |
| +Reviewed platform `08467448` and website `1fa82b9`. All 28 release ranges and 363 unique changes’ own-commit counts match Git; vendored data matches. Existing website checks and in-memory rendering ran. Go tests could not start because the sandbox prevents creating their work directory; full `npm run check` requires writes. No files edited. |
| + |
| +**accept with fixes** |
| \ No newline at end of file |
diff --git a/internal/changelog/build.go b/internal/changelog/build.go| index 80eaa6025..0416778c8 100644 |
| --- a/internal/changelog/build.go |
| +++ b/internal/changelog/build.go |
| @@ -5,6 +5,7 @@ import ( |
| "fmt" |
| "html" |
| "net/url" |
| + "path" |
| "regexp" |
| "slices" |
| "sort" |
| @@ -631,13 +632,15 @@ func decodedForms(s string) []string { |
| // What a browser makes of markdown emphasis and dot segments: |
| // "**ops@example**.org" reads as an address, and |
| // "carlosframework/./platform" resolves to the private repo. |
| - plain := dotSegmentRe.ReplaceAllString(emphasisRe.ReplaceAllString(all, ""), "/") |
| + plain := githubPathRe.ReplaceAllStringFunc(emphasisRe.ReplaceAllString(all, ""), func(m string) string { |
| + return "github.com" + path.Clean(m[len("github.com"):]) |
| + }) |
| return []string{s, ent, md, pct, all, plain} |
| } |
| var ( |
| emphasisRe = regexp.MustCompile("[*_`~]+") |
| - dotSegmentRe = regexp.MustCompile(`/(\./)+`) |
| + githubPathRe = regexp.MustCompile(`(?i)github\.com/[^\s)"'<>\]]*`) |
| ) |
| func checkPublicText(s string, people People) error { |
diff --git a/internal/changelog/build_test.go b/internal/changelog/build_test.go| index 1af759d28..19ddf7de7 100644 |
| --- a/internal/changelog/build_test.go |
| +++ b/internal/changelog/build_test.go |
| @@ -245,6 +245,7 @@ func TestCheckPublic(t *testing.T) { |
| "ops&#64;example.org", |
| "see **ops@example**.org now", |
| "[source](https://github.com/carlosframework/./platform)", |
| + "[source](https://github.com/carlosframework/public/../platform.git)", |
| } { |
| bad := &Changelog{Releases: []Release{{Tag: "v1.0.0", Changes: []Change{{Subject: s}}}}} |
| if err := CheckPublic(bad, testPeople); err == nil { |