Skip to content

Security hardening: URL/image allowlists, genos:// caps, credential redaction#7

Open
Vext-Labs wants to merge 3 commits into
thesysdev:mainfrom
Vext-Labs:agent/fix-security
Open

Security hardening: URL/image allowlists, genos:// caps, credential redaction#7
Vext-Labs wants to merge 3 commits into
thesysdev:mainfrom
Vext-Labs:agent/fix-security

Conversation

@Vext-Labs

Copy link
Copy Markdown

What

A small, additive security-hardening pass over the model-output trust boundary, from a short audit of how LLM-generated content flows into device capabilities. Each fix is independent and test-backed; the audit's verified-clean areas (no committed secrets, no console.*, keys only sent as Authorization headers, the DSL evaluator being an AST walker with no eval) are noted in SECURITY.md.

Findings addressed (severity-ranked in our audit; file refs against current main):

  1. URL scheme allowlist (GenOS.tsx handleAction) — any model-emitted URL was passed to Linking.openURL unfiltered, including javascript:, intent:, tel:/sms: with prefilled bodies, and arbitrary app schemes. New src/genos/safety/urlPolicy.ts opens only http(s): and shows a "That link type isn't supported" toast otherwise.
  2. Image host policy (tools/images.ts) — model-supplied image URLs were fetched directly, which lets generated content make the device GET arbitrary URLs (a potential conversation-context exfil channel). Hosts are now allowlisted (images.unsplash.com, loremflickr.com, upload.wikimedia.org); anything else falls back to the existing LoremFlickr semantic path.
  3. genos:// hardening (safety/genosLink.ts) — genos://open accepted arbitrary app ids and unbounded request text that is injected as a user message; ids are now allowlisted (known apps or ^[a-z0-9-]{1,32}$) and requests capped at 300 chars. genos://toast text is capped at 120 chars.
  4. Credential redaction (store.ts) — values of password-shaped form fields were replayed into model context via formState; they are now redacted before replay. (Heuristic keys off field names — noted in code; a contract-level field-type fix felt like your call to make.)
  5. secureTextEntry on the KeyGate API-key input.

Also adds SECURITY.md with a vulnerability-reporting path and honest hardening notes (this is a pass, not a claim of completeness).

What this deliberately does NOT change

  • src/genos/telemetry.ts — the hardcoded PostHog project key means forks' users report into your analytics by default. That's a policy decision for you, so we left it untouched and documented it in SECURITY.md instead of unilaterally changing it.

Test plan

  • npm run typecheck
  • npm test — 34 passed (22 existing + 12 new in __tests__/security.test.ts) ✓
  • Verified the blocked-scheme toast, image fallback, and redaction paths in the new tests.

Contributed by Vext Labs.

New src/genos/safety modules enforcing at runtime what the system prompt
can only request:
- urlPolicy: only http(s) links reach Linking; every other scheme blocked
- genosLink: genos://open targets validated (catalog ids or safe slug
  shape), requests capped at 300 chars, toast text at 120
- redaction: credential-shaped form values replaced with [redacted]
- tools/images: model-supplied image URLs resolve only on allowlisted
  https hosts, else fall back to the LoremFlickr semantic path
- GenOS.handleAction routes external URLs through openExternalUrl with a
  blocked-link toast, and genos:// links through parseOpenLink/capToastText
- store.resolveAction redacts credential-shaped form values before they
  are sent to the provider or replayed as context; openDeepLink re-caps
  the injected request (defense in depth)
- KeyGate masks the API-key entry field (secureTextEntry)
- media.tsx documents that raw URLs pass the image-host policy first
12 tests covering the scheme allowlist (javascript:/intent:/sms:/etc
blocked), deep-link caps and app-id validation, password redaction into
the provider request, and the image-host policy with its LoremFlickr
fallback. SECURITY.md adds a reporting policy plus honest hardening
notes and limits.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant