Course outline

Vue / Advanced: architecture, hydration, and production evidence / Lesson 15

Security and untrusted data boundaries

Preserve text, URL, identity, and server trust boundaries while keeping client code free of privileged secrets.

About 4 min readContent reviewed
On this page

Lesson goals

  • Distinguish safe text rendering from trusted HTML or templates.
  • Validate URL and authorization context at the correct layer.

Never turn untrusted content into a Vue template

Vue’s normal text interpolation escapes values for display, while a template is executable application structure. Do not compile user-controlled strings as Vue templates or mount onto untrusted HTML that becomes template source. v-html inserts HTML deliberately and requires a reviewed content policy, often maintained sanitization when rich content is needed. Escaping text, validating a URL, sanitizing HTML, and authorizing data access solve different problems. A framework can provide safe defaults only when the application preserves their intended boundaries. Treat third-party components and content processors as dependencies with their own trust and update requirements.

Use ordinary text rendering for ordinary content

The component displays a message through normal interpolation and does not interpret it as HTML. That is the correct default for a note title or plain message. It does not decide whether the current account may read that message; server-side authorization and data minimization must happen before private information is delivered to the client. Once sensitive content reaches a browser, hiding it with a directive is not a confidentiality boundary. Keep logging and error reporting from collecting the message unnecessarily. The example contains no hostile payload and makes no live request.

vue A plain-text display boundary
<script setup>
const props = defineProps({ message: { type: String, required: true } })
</script>

<template>
  <p>{{ props.message }}</p>
</template>

A supplied message such as Notes & references is displayed as text under Vue’s escaping rules. The component performs no rich-HTML insertion, authorization, or persistence. Browser rendering was not executed for this fragment.

Apply a URL policy before binding navigation

Escaping an attribute does not make every URL scheme or destination acceptable. Define allowed protocols, origins, paths, and user-information rules according to the feature, preferably before data reaches the client. The standalone helper below permits only a synthetic HTTPS origin and rejects credentials embedded in a URL. It normalizes relative paths against that origin without contacting it. This is a deliberately narrow policy for the example, not a complete sanitizer or server-side access control. A legitimate-looking link can still lead to unauthorized content unless the destination enforces its own policy.

javascript A complete offline URL allowlist example
function allowedNoteUrl(value) {
  if (typeof value !== "string") return null
  try {
    const base = new URL("https://notes.example.invalid/")
    const url = new URL(value, base)
    if (url.origin !== base.origin || url.protocol !== "https:" || url.username || url.password) return null
    return url.href
  } catch {
    return null
  }
}
if (allowedNoteUrl("/read/n1") !== "https://notes.example.invalid/read/n1") {
  throw new Error("URL_NORMALIZATION_MISMATCH")
}
if (allowedNoteUrl("https://other.example.invalid/read") !== null) {
  throw new Error("URL_ORIGIN_POLICY_MISMATCH")
}

Runs under Node using the URL parser and reserved .invalid example domains. No DNS lookup or request occurs. The assertions check one allowed relative path and one rejected origin, not every possible URL or product policy.

Keep privileged trust off the client

Client bundles, source maps, browser storage, and public environment variables can be inspected by users. Do not place a backend master secret in a Vue source file or assume a build prefix makes it private. Authentication tokens, session cookies, and identity integration need an approved application design; a tutorial store is not a secure credential vault. Protect write operations against the threats relevant to the server session model, including request authenticity where required. Route guards and disabled buttons improve user experience but cannot enforce server permission. Avoid logging private payloads or full credential-bearing URLs during debugging.

Verify the actual boundary and update dependencies

Review raw-output exceptions, URL consumers, component dependencies, server authorization, and state serialization. Test allowed and denied behaviors in an authorized isolated environment and include ordinary legitimate use so a defense does not merely break the feature. Security-related framework updates and advisories need review against the pinned baseline; a green component test cannot establish absence of all vulnerabilities. For SSR, use supported state serialization and never insert untrusted serialized data into HTML through an improvised string concatenation. This course demonstrates benign local parsing only and performs no scanning, exploitation, credential handling, or service changes.

Common errors and fixes

User content is compiled as a template

Why it happens
Data is promoted into executable component structure.
How to fix it
Render text or use a reviewed rich-content boundary.
Prevent it next time
Keep template sources trusted.

An escaped URL points to an unapproved destination

Why it happens
Encoding is confused with protocol and destination validation.
How to fix it
Apply the feature’s URL policy before binding.
Prevent it next time
Test schemes, origins, and malformed input safely.

A build variable exposes a privileged secret

Why it happens
Client configuration is mistaken for private server storage.
How to fix it
Remove the secret and follow its owner’s exposure-response process.
Prevent it next time
Review every client-visible configuration field.

Check your understanding

1. Does hiding a private record with v-if prevent disclosure after it is sent to the browser?

Show worked solution

No. The client already received the data. The server must authorize and minimize what it returns. Visibility is a user-interface choice, not a substitute for the confidentiality boundary.

2. A URL helper accepts the right origin. Does it authorize the destination record?

Show worked solution

No. It supports a narrow navigation policy. The destination still authenticates and authorizes access to the record, and any path restrictions required by the feature need their own explicit checks.

Key takeaways

  • Text, HTML, templates, URLs, and permissions have separate boundaries.
  • Client code cannot keep privileged server secrets private.
  • Use maintained safe APIs and verify their actual scope.

Official references