fix(competitive-intel): scheme-allowlist BoardTable evidence links - #550
Merged
Conversation
This was referenced Aug 3, 2026
added 3 commits
August 3, 2026 20:07
…SS defense-in-depth) Adversarial review of #545 flagged: BoardTable.vue bound `:href` from `cell(...).evidence!.href` (competitiveBoardsApi JSON) with no scheme allowlist. `rel="noopener noreferrer"` is present but doesn't help — the JS in a `javascript:` href runs before a tab exists. Today's source is estate-internal (dashboard-bff/catalog-gateway JSON or bundled fixtures with hardcoded https://github.com/SocioProphet URLs), so this is defense-in-depth rather than an active exploit path. Same class of fix as #477 (Search.vue) — ported the helper to client-vue as `utils/urlSafe.ts` since app-vue's `services/url-safe.ts` isn't shared across the two packages. Unsafe evidence hrefs now render as plain text (label only, no link) instead of a live anchor. 10 test cases pin the allow/deny boundary.
…test glob This file was added a few commits ago on this branch as a copy-paste of app-vue's url-safe.ts (same defect class, same fix) because the two Vue packages don't share a workspace. That duplication is exactly what SourceOS-Linux/sourceos-spec#276 exists to close: repoints this file to be a byte-identical vendored copy of estate-safety-kit/js/urlSafe.ts, with PROVENANCE.txt recording the source commit. app-vue's copy is being converted the same way on a separate PR (SocioProphet/socioprophet's chore/vendor-estate-safety-kit branch), since it already existed on master. No logic change — the vendored file is behavior-identical to what was already here (comments only differ). Also: vite.config.ts's vitest `include` was `src/__tests__/**/*.test.ts` only, so `npm test` never actually ran src/utils/urlSafe.test.ts, added earlier on this branch — the 12 tests pinning the allow/deny boundary existed but were never executed. Added a second glob scoped to src/utils/**/*.test.ts to fix that (deliberately not widened to src/**/*.test.ts — several other pre-existing test files elsewhere in this package are also out-of-glob with unverified pass/fail state; that is a separate, broader cleanup, flagged out-of-band rather than folded in here). Full suite after both changes: 124 files / 739 tests pass, including the 12 in urlSafe.test.ts.
The estate-safety-kit vendoring commit narrowly widened test.include to `['src/__tests__/**/*.test.ts', 'src/utils/**/*.test.ts']` to pick up urlSafe.test.ts specifically, and explicitly punted a broader fix: 6 other pre-existing, real (non-stub) test files sat outside BOTH globs — src/config/mesh.test.ts, src/features/contract-surfaces/contractSurfaces .test.ts, and 4 files under src/runtime-adapters/ (knowledgeGraphClient, ontologyClient, rescuedPlatformFeatures, routeRuntimeFeatures). `npm test`/CI never executed them. Same declared-but-unenforced shape as everything else this session has been closing — a test file existing is not the same as a test file running. Widened `include` to `src/**/*.test.ts`, replacing both narrower globs. Verified rather than assumed clean: - Full suite: 130 test files / 783 tests, all pass. - The 6 previously-orphaned files run in isolation: 6/6 files, 44/44 tests, all pass — nothing was actually stale or broken, they were just never executed. No test-content fixes were needed. - `vue-tsc --noEmit`: clean. The noisy ECONNREFUSED/AbortError console output during the full run is expected — live-adapter fallback tests intentionally hit an unreachable localhost:3000 to exercise the degraded path; vitest's own pass/fail accounting (783/783) is unaffected by it.
mdheller
force-pushed
the
fix/boardtable-scheme-allowlist
branch
from
August 4, 2026 00:08
bb148f0 to
701396c
Compare
…rge commit Same fix as #551 — sourceos-spec#276 merged (squash) as 297c4e38, the provisional branch-head pin is now dead. Verified byte-identical before re-pinning.
mdheller
enabled auto-merge (squash)
August 4, 2026 00:32
mdheller
added a commit
that referenced
this pull request
Aug 4, 2026
* chore(app-vue): vendor url-safe.ts from estate-safety-kit, not a hand-maintained copy isSafeHttp was independently written here (#477) and then copy-pasted (not imported) into client-vue's utils/urlSafe.ts (#550) because the two Vue packages don't share a workspace — the exact kind of duplication SourceOS-Linux/sourceos-spec#276 exists to close. This repoints app-vue's copy to be a byte-identical vendored copy of estate-safety-kit/js/urlSafe.ts, with PROVENANCE.txt recording the source commit. client-vue's copy is being converted the same way on #550's branch, since that file doesn't exist on master yet. No behavior change: the vendored file is logic-identical to what was here (comments only differ — the canonical version documents both consumers and the vendoring contract instead of just this one). Confirmed with the existing test suite unchanged: 65/65 app-vue tests pass, including all 52 in url-safe.test.ts covering the allow/deny scheme boundary. * chore(app-vue): re-pin PROVENANCE.txt to the real sourceos-spec merge commit sourceos-spec#276 merged (squash) as 297c4e38 — the branch-head SHA this PROVENANCE.txt provisionally pinned no longer exists as a live ref. Verified byte-identical against the new pin before re-pinning (sha256 9493df8b... both sides), so this closes the provisional-pin TODO the file itself flagged rather than leaving it to rot. --------- Co-authored-by: Michael Heller <charles.peterson@socioprophet.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(competitive-intel): scheme-allowlist BoardTable evidence links (XSS defense-in-depth)
Adversarial review of #545 flagged: BoardTable.vue bound
:hreffromcell(...).evidence!.href(competitiveBoardsApi JSON) with no schemeallowlist.
rel="noopener noreferrer"is present but doesn't help — theJS in a
javascript:href runs before a tab exists.Today's source is estate-internal (dashboard-bff/catalog-gateway JSON or
bundled fixtures with hardcoded https://github.com/SocioProphet URLs), so
this is defense-in-depth rather than an active exploit path. Same class
of fix as #477 (Search.vue) — ported the helper to client-vue as
utils/urlSafe.tssince app-vue'sservices/url-safe.tsisn't sharedacross the two packages.
Unsafe evidence hrefs now render as plain text (label only, no link)
instead of a live anchor. 10 test cases pin the allow/deny boundary.
Update (2026-08-03):
utils/urlSafe.tshere has been re-pointed to abyte-identical vendored copy of the canonical helper in
SourceOS-Linux/sourceos-spec#276
(
estate-safety-kit/js/urlSafe.ts), which also folds inapp-vue'sservices/url-safe.ts— the two had converged to identical logic despitebeing maintained separately.
utils/PROVENANCE.txtrecords the sourcecommit;
tools/check_vendored_safety_kit.pyin that repo can verify thecopy is still byte-identical. Dependency ordering: sourceos-spec#276 is
open, not merged — this PR's
PROVENANCE.txtpin is provisional (points atthe PR branch head, which GitHub still serves) and should be updated to the
eventual merge commit once #276 lands. Not blocking this PR's merge on
that; noting the dependency explicitly per the vendoring contract in #276.
Also fixed in the same commit:
vite.config.ts's vitestincludenevermatched
src/utils/**, sonpm testwas silently never runningurlSafe.test.ts's 12 cases. Full suite after both changes: 124 files /739 tests pass.
See also SocioProphet/socioprophet chore/vendor-estate-safety-kit
(app-vue's equivalent conversion).