This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: capacitor-7-scoped-storage-photopicker-sandbox

Capacitor 7 Scoped Storage PhotoPicker Sandbox Fencing & Descriptor Recycling

Enforces strict Scoped Storage fencing, explicit URI permission acquisition, and immediate native FileDescriptor recycling for Capacitor 7 running on modern Android target SDKs (34+). Prevents silent process death from kernel file descriptor exhaustion and invalid URI persistence failures across Android activity recreation.

Prohibited Anti-Pattern: Leaking Transient Content URIs and Raw File Descriptors Across the Capacitor Web-Native Bridge

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Capacitor 7 Scoped Storage PhotoPicker Sandbox Fencing & Descriptor Recycling - Enforces strict Scoped Storage fencing, explicit URI permission acquisition, and immediate native FileDescriptor recycling for Capacitor 7 running on modern Android target SDKs (34+). Prevents silent process death from kernel file descriptor exhaustion and invalid URI persistence failures across Android activity recreation.
globs: android/app/src/main/**/*.kt, android/app/src/main/**/*.java, src/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/capacitor-7-scoped-storage-photopicker-sandbox"
---

# Capacitor 7 Scoped Storage PhotoPicker Sandbox Fencing & Descriptor Recycling

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Leaking Transient Content URIs and Raw File Descriptors Across the Capacitor Web-Native Bridge

## System Constraints
You are a Principal Mobile Architect specializing in Capacitor 7, modern Android NDK/SDK internals, and Linux kernel descriptor management. Enforce strict sandboxed storage fencing and explicit descriptor lifecycle bounds for all media ingestion pipelines. Mandate that all Android PhotoPicker results fence content URIs within internal cache storage immediately and release ContentResolver resources to avoid native descriptor leaks.

## Strict Guidelines
- Engineers MUST NEVER query deprecated MediaStore columns (such as `_data`) to reconstruct absolute file system paths under Android API 29+.
- Engineers MUST ALWAYS wrap `ContentResolver.openFileDescriptor` or `ContentResolver.openInputStream` in `use { ... }` (Kotlin) or `try-with-resources` (Java) to prevent native Linux file descriptor exhaustion.
- Engineers MUST NOT pass raw `content://` URIs directly to the Capacitor WebView; media MUST be staged to `context.cacheDir` and resolved via `Capacitor.convertFileSrc()` or native custom scheme handling.
- Engineers MUST explicitly call `contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)` if a content URI is persisted beyond the current Activity lifecycle, catching `SecurityException` gracefully.
- Services MUST implement automatic cache eviction policies for sandboxed media replicas to avoid unbounded internal storage growth in long-running applications.
- Components NEVER store transient native pointers, `ParcelFileDescriptor`, or unclosed streams across asynchronous Capacitor plugin bridge boundaries.

## Bad vs Good Implementations
### Android Plugin Descriptor Leak and Insecure URI Persistence vs Sandboxed Fencing

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Raw content URIs generated by the Android PhotoPicker grant transient permissions bound only to the originating Intent lifecycle. Storing them in localStorage guarantees broken image references upon process recreation, while direct fetch inside the WebView causes CORS/CSP violations or security exceptions under Android Target SDK 34+.
```typescript
import { Plugins } from '@capacitor/core';
// ANTI-PATTERN: Passing raw content URI to WebView, assuming perpetual read access
// and failing to handle sandboxed staging or descriptor recycling.
export async function handlePickedPhoto(rawContentUri: string): Promise<string> {
  // Crashes after activity death or when Android revokes transient grant
  const response = await fetch(rawContentUri);
  const blob = await response.blob();
  localStorage.setItem('cachedPhotoUri', rawContentUri);
  return URL.createObjectURL(blob);
}
```

#### Production Standard (Correct)
> **Standard**: Fences the transient Android PhotoPicker file descriptor into the application's private cache partition (`Directory.Cache`). The native FileDescriptor is consumed and closed deterministically, transient URI permissions are bypassed, and the web layer receives a deterministic path via `Capacitor.convertFileSrc`.
```typescript
import { Capacitor } from '@capacitor/core';
import { Filesystem, Directory } from '@capacitor/filesystem';

interface StagedMediaResult {
  webPath: string;
  sandboxPath: string;
}

// PRODUCTION INVARIANT: Stream into isolated internal cache, fence permissions, and return WebView-safe URL
export async function stagePickerMediaToSandbox(nativeUri: string): Promise<StagedMediaResult> {
  const fileName = `picker_${Date.now()}_${crypto.randomUUID().slice(0, 8)}.bin`;
  
  // Copy via bridge to guarantee native FileDescriptor closure and sandbox ownership
  const copyResult = await Filesystem.copy({
    from: nativeUri,
    to: fileName,
    toDirectory: Directory.Cache
  });

  const webPath = Capacitor.convertFileSrc(copyResult.uri);
  
  return {
    webPath,
    sandboxPath: copyResult.uri
  };
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Capacitor 7 Scoped Storage PhotoPicker Sandbox Fencing & Descriptor Recycling

Capacitor 7 Scoped Storage PhotoPicker Sandbox Fencing & Descriptor Recycling defines an industrial-grade behavioral standard for mobile engineering. Enforces strict Scoped Storage fencing, explicit URI permission acquisition, and immediate native FileDescriptor recycling for Capacitor 7 running on modern Android target SDKs (34+). Prevents silent process death from kernel file descriptor exhaustion and invalid URI persistence failures across Android activity recreation. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Leaking Transient Content URIs and Raw File Descriptors Across the Capacitor Web-Native Bridge Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftLeaking Transient Content URIs and Raw File Descriptors Across the Capacitor Web-Native BridgeCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST NEVER query deprecated MediaStore columns (such as `_data`) to reconstruct absolute file system paths under Android API 29+.

Engineers MUST NEVER query deprecated MediaStore columns (such as `_data`) to reconstruct absolute file system paths under Android API 29+.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST ALWAYS wrap `ContentResolver.openFileDescriptor` or `ContentResolver.openInputStream` in `use { ... }` (Kotlin) or `try-with-resources` (Java) to prevent native Linux file descriptor exhaustion.

Engineers MUST ALWAYS wrap `ContentResolver.openFileDescriptor` or `ContentResolver.openInputStream` in `use { ... }` (Kotlin) or `try-with-resources` (Java) to prevent native Linux file descriptor exhaustion.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST NOT pass raw `content

Engineers MUST NOT pass raw `content://` URIs directly to the Capacitor WebView; media MUST be staged to `context.cacheDir` and resolved via `Capacitor.convertFileSrc()` or native custom scheme handling.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Engineers MUST explicitly call `contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)` if a content URI is persisted beyond the current Activity lifecycle, catching `SecurityException` gracefully.

Engineers MUST explicitly call `contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)` if a content URI is persisted beyond the current Activity lifecycle, catching `SecurityException` gracefully.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Services MUST implement automatic cache eviction policies for sandboxed media replicas to avoid unbounded internal storage growth in long-running applications.

Services MUST implement automatic cache eviction policies for sandboxed media replicas to avoid unbounded internal storage growth in long-running applications.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
6

Components NEVER store transient native pointers, `ParcelFileDescriptor`, or unclosed streams across asynchronous Capacitor plugin bridge boundaries.

Components NEVER store transient native pointers, `ParcelFileDescriptor`, or unclosed streams across asynchronous Capacitor plugin bridge boundaries.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Capacitor 7 Scoped Storage PhotoPicker Sandbox Fencing & Descriptor Recycling critical for AI coding assistants?

Enforces strict Scoped Storage fencing, explicit URI permission acquisition, and immediate native FileDescriptor recycling for Capacitor 7 running on modern Android target SDKs (34+). Prevents silent process death from kernel file descriptor exhaustion and invalid URI persistence failures across Android activity recreation. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Leaking Transient Content URIs and Raw File Descriptors Across the Capacitor Web-Native Bridge) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

Related MOBILE Rules

View all rules →
1 Rule in Stack

Capacitor