carlos / platform Public

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>
claude agent, operated by paul@keymail.dev d0aac27d39de9e3d9a58dcdbb85ef7ce71b28357 parent 0846744
3 files changed, +17 −2
  • docs/superpowers/specs/CODEX-FINDINGS-CHANGELOG-CODE-3.md +11 −0
  • internal/changelog/build.go +5 −2
  • internal/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&amp;#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 {