An MCP resource is not just a nicer filename.
It is context waiting to cross a boundary.
Short answer
Treat MCP resources as context ingress. Before a resource or resource template can reach a model, review its URI scheme, source system, selection path, content type, trust label, sensitive data class, automatic inclusion behavior, model selection behavior, subscription behavior, template parameters, access control, downstream tool path, and log location. If a server can expose sensitive data or untrusted content as high-priority assistant context, require narrow access, explicit selection, source labels, and separate approval before tools or external communication can use it.
What MCP resources change
Most MCP security reviews start with tools.
That is reasonable. Tools can read, write, send, delete, deploy, query, or call another API. They are easy to recognize as power.
Resources look quieter.
The MCP resources specification says resources let servers share data that provides context to language models. Examples include files, database schemas, and application-specific information. Each resource is identified by a URI.
That makes resources part of the context boundary.
The server is not only saying, "I can do these actions." It may also be saying, "Here is data the model can use."
That data may be trusted project documentation. It may be a database schema. It may be a customer record. It may be a generated report. It may be a downloaded file with hostile instructions inside it.
The review should happen before the model treats that data as useful context.
Resource selection is a security decision
The spec is flexible about how resources enter context.
Host applications can expose resources through UI selection, search and filtering, automatic inclusion based on heuristics, or the AI model's selection. The protocol does not require one interaction model.
That flexibility is useful. It also means the security model lives in the client and workflow, not only in the protocol.
There is a big difference between these patterns:
- A user explicitly selects one read-only project file.
- A client automatically includes every recent resource from a server.
- A model selects resources based on a prompt that contains untrusted content.
- A resource template lets the server read a broad path or object class.
Those are not the same risk.
For sensitive workflows, automatic inclusion should be off until the resource class is understood. Model-selected resources should have visible trust and sensitivity labels. Search and filtering should not hide where the data came from.
The question is not only, "Can the server list resources?"
It is, "How does this resource actually reach the model?"
URI schemes and templates are part of the boundary
MCP resources are identified by URIs. The spec lists common schemes such as https://, file://, and git://, and it allows custom URI schemes.
That matters because the scheme hints at the source and control model.
A file:// resource behaves like filesystem data. An https:// resource may point at web content. A git:// resource may represent source history or repository state. A custom scheme may hide an application-specific boundary unless the client explains it.
Resource templates deserve extra review.
The spec lets servers expose parameterized resources using URI templates. A template is useful when the user needs a family of resources, such as files, issues, records, or schema objects.
It can also turn one approval into a wide read surface.
Before approving a template, write down:
Template:
Allowed parameters:
Blocked parameters:
Source system:
Expected content type:
Sensitive data class:
Access control check:
Who can choose values:
Log location:
If a template accepts arbitrary paths, broad IDs, wildcard searches, or user-controlled URLs, treat it as a higher-risk input path.
Annotations are not trust labels
The resources spec supports annotations for audience, priority, and last modified time. Clients can use those annotations to filter, prioritize, or display resources.
Those hints are useful. They are not enough.
Keep reading with free field-guide resources.
VibeSec Advisory publishes practical research, Skills, workflow examples, MCP notes, prompt injection tests, and AI red-team lessons for builders working with agentic AI.
A high-priority resource can still be untrusted. A resource intended for the assistant can still contain sensitive data. A recent resource can still be malicious, stale, or irrelevant to the workflow.
Add labels the model and reviewer actually need:
Trust label: trusted internal, user supplied, external, generated, unknown
Sensitivity: public, internal, confidential, credential, personal data, regulated
Source owner: team or system responsible for the resource
Selection mode: explicit, search, automatic, model selected
Allowed use: summarize, quote, transform, compare, feed tool, blocked
Do not let priority: 1.0 become a shortcut around trust review.
Resources can carry prompt injection
OWASP LLM01: Prompt Injection says indirect prompt injection can happen when an LLM accepts input from external sources such as websites or files. OWASP also says prompt injection can lead to sensitive information disclosure, unauthorized function access, arbitrary commands in connected systems, and manipulation of decisions.
That maps directly to resources.
A resource can be a README. A web page. A file from a repository. A generated issue export. A document from a customer. A schema comment. A binary blob converted into text. A custom app object with notes from another user.
If that content reaches the model, it should be treated as data, not instruction.
The safer pattern:
- Label untrusted resources before inclusion.
- Keep untrusted resource text separate from system and developer instructions.
- Prevent untrusted resources from changing tool permissions or approval prompts.
- Test with a hostile resource that tells the agent to reveal secrets or call a tool.
- Log whether the client ignored, quoted, summarized, or acted on the hostile text.
Prompting alone is not enough. The workflow needs a boundary the model cannot rewrite.
Sensitive resources need a default-deny path
OWASP LLM02: Sensitive Information Disclosure lists sensitive information categories that fit MCP resource review:
- Personal identifiable information
- Financial details
- Health records
- Confidential business data
- Security credentials
- Legal documents
The MCP resources spec also says access controls should be implemented for sensitive resources and resource permissions should be checked before operations.
Put those together and the default should be simple.
Sensitive resources do not enter automatic context.
If a workflow needs sensitive resource access, require a narrow reason, a named owner, user or workflow-scoped access, redaction where possible, retention clarity, and a log.
Do not rely on a system prompt that says, "Do not reveal sensitive data." OWASP notes that prompt restrictions may not always be honored and may be bypassed through prompt injection or other methods.
The control should be structural.
Subscriptions and resource changes need a log
Resources are not always static.
The MCP spec supports list-changed notifications and optional subscriptions to individual resource updates. That means the resource set or resource contents can change after the initial approval.
That is useful for live workflows. It also creates a review problem.
A resource approved yesterday may not be the same resource today. A server that starts with safe project docs may later expose logs, generated files, user uploads, or broader application records. A subscribed resource may refresh with new content from an untrusted source.
Log these changes:
Resource changed:
Old trust label:
New trust label:
Sensitive data class changed:
Automatic inclusion changed:
Subscription enabled:
Reviewer:
Decision:
If a client cannot show when a resource list changed, treat automatic resource inclusion as too trusted for sensitive workflows.
Resources plus tools create agency
A resource usually does not act by itself.
The risk increases when resource content can feed tools.
OWASP LLM06: Excessive Agency frames the relevant failure mode as excessive functionality, excessive permissions, or excessive autonomy. OWASP recommends minimizing extensions, minimizing functionality, minimizing permissions, requiring user approval, and using complete mediation.
For MCP resources, the review question is:
What can happen after this resource reaches context?
Examples:
- A database schema resource plus a read-only query tool is one risk.
- A customer record resource plus an email tool is a higher risk.
- A repository file resource plus a write, commit, or deployment tool needs a separate approval gate.
- A web resource plus a browser or network tool can become an exfiltration path.
- A generated resource plus shell access is not a safe default.
Do not approve resources and tools in separate rooms.
The safe review connects them.
The MCP resource context review record
Before enabling resource access for an MCP server, write this down:
MCP client:
MCP server:
Workflow using the resource:
Resource URI or template:
URI scheme:
Source system:
Content type:
Selection path:
Automatic inclusion allowed:
Model selection allowed:
Trust label:
Sensitive data class:
Untrusted content path:
Audience and priority annotations:
Template parameters:
Subscription or update behavior:
Access control checked:
Can resource feed tools:
Can output leave the system:
Default decision if unclear:
Log location:
Owner:
Review date:
If a team cannot fill this out, it probably cannot explain the context boundary.
Deny or narrow these resources
Deny or narrow resource access when:
- The URI scheme is unclear.
- A custom scheme hides the source system.
- A template accepts broad paths, wildcard IDs, or user-controlled URLs.
- Automatic inclusion is enabled for unknown, sensitive, or user-supplied content.
- Model selection can pull resources with no trust label.
- Sensitive data can enter context without a named owner and access control check.
- Resource annotations prioritize content without showing trust or sensitivity.
- Subscriptions can refresh content without a visible change log.
- A resource can feed write, delete, send, deploy, shell, browser, or external API tools without a separate approval gate.
- The client cannot show which resource influenced a tool call or final answer.
This is not about blocking MCP resources.
It is about refusing to treat context as harmless just because it is not a tool call.
Evidence versus opinion
Evidence from the sources:
- The MCP resources specification says resources provide context to language models, including files, database schemas, and application-specific information.
- The resources spec allows explicit selection, search and filtering, automatic inclusion, and model-selected resource use depending on the host application.
- The resources spec supports URI schemes, resource templates, text and binary content, annotations, subscriptions, and list-changed notifications.
- The resources spec says servers must validate resource URIs and should implement access controls and permission checks for sensitive resources.
- MCP security best practices frame MCP implementations as security review subjects and include consent, token, local server, and scope-minimization concerns.
- OWASP LLM01 frames external files and websites as possible indirect prompt injection sources.
- OWASP LLM02 defines sensitive information classes and warns that prompt restrictions can be bypassed.
- OWASP LLM06 frames excessive agency around functionality, permissions, autonomy, approval, and complete mediation.
My opinion:
MCP resources should get their own context review. The safest default is explicit resource selection, narrow templates, visible source labels, trust labels, sensitive data classes, subscription logs, and separate approval before resource content can drive write-capable or externally communicating tools.
If a resource can quietly become model context, it deserves the same scrutiny as any other input boundary.
Free next step
Review one MCP server you use. List every resource and resource template, add a trust label to each one, then disable automatic inclusion for unknown or sensitive resources until you can fill out the review record above. If a resource can feed tools, compare it against the MCP permission review, the MCP sampling approval gate, the MCP elicitation sensitive data gate, and the MCP roots file access review.