Back to skill

Security audit

neon-realtime

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Neon Realtime documentation skill with expected database, auth, environment, and subscription guidance, not hidden or purpose-mismatched behavior.

Install only if you are building with Neon Realtime and are comfortable granting the agent access to project code, Neon CLI setup, and database/auth configuration. Keep NEON_REALTIME_SECRET, DATABASE_URL, cookie secrets, and sealed queries out of browser bundles, logs, URLs, and shared caches.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (15)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 174)May include surrounding context.

md
y.md](references/reactivity.md) before writing React or TanStack DB code. Read [references/subscribing.md](references/subscribing.md) before subscribing directl

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 183)May include surrounding context.

md
Realtime has no write path, so writes keep your backend's usual auth. Read [references/mutations.md](references/mutations.md) before writing mutations, for each

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 185)May include surrounding context.

md
Realtime has no write path, so writes keep your backend's usual auth. Read [references/mutations.md](references/mutations.md) before writing mutations, for each

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/queries.md (reported line 96)May include surrounding context.

Vite expands $VAR in env files, and neon env pull keeps lines it doesn't manage, so point them at the server variables:

bash
echo 'VITE_NEON_AUTH_URL=$NEON_AUTH_BASE_URL' >> .env.local
echo 'VITE_NEON_REALTIME_URL=$NEON_REALTIME_URL' >> .env.local

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/queries.md (reported line 97)May include surrounding context.

Vite expands $VAR in env files, and neon env pull keeps lines it doesn't manage, so point them at the server variables:

bash
echo 'VITE_NEON_AUTH_URL=$NEON_AUTH_BASE_URL' >> .env.local
echo 'VITE_NEON_REALTIME_URL=$NEON_REALTIME_URL' >> .env.local

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/ssr.md (reported line 211)May include surrounding context.

Vite expands $VAR in env files, and neon env pull keeps lines it doesn't manage, so point them at the server variables:

bash
echo 'VITE_NEON_AUTH_URL=$NEON_AUTH_BASE_URL' >> .env.local
echo 'VITE_NEON_REALTIME_URL=$NEON_REALTIME_URL' >> .env.local

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/ssr.md (reported line 450)May include surrounding context.

Vite expands $VAR in env files, and neon env pull keeps lines it doesn't manage, so point them at the server variables:

bash
echo 'VITE_NEON_AUTH_URL=$NEON_AUTH_BASE_URL' >> .env.local
echo 'VITE_NEON_REALTIME_URL=$NEON_REALTIME_URL' >> .env.local

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · SKILL.md (reported line 12)May include surrounding context.

FIRST: Use the parent neon skill for a Neon overview, getting started with Neon, Neon development best practices, and more.

If the neon skill is not installed, fetch it from https://neon.com/docs/ai/skills/neon/SKILL.md or install it with:

bash
neon skills -s neon -y

Context Window Stuffing

Medium
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill attempts to fill the context window with filler content, displacing legitimate instructions and safety constraints. This can degrade agent performance or bypass safety boundaries.

Content

Scanner excerpt · references/subscribing.md (reported line 233)May include surrounding context.

md
A subscription has three callbacks. Each one takes a listener and returns a function that removes it:

| Callback        | Listener arguments                 | Fires                                                                                                                                                                                                                                                                                                                            |
| --------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onChange`      | `snapshot: LiveQuerySnapshot<Row>` | After each state change, after each `changes` update while `live`, and when a new result is complete. Materialized subscriptions only.                                                                                                                                                                                           |
| `onStateChange` | `state: LiveQueryState`            | When the status changes.                                                                                                                                                                                                                                                                                                         |

Context Window Stuffing

Medium
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill attempts to fill the context window with filler content, displacing legitimate instructions and safety constraints. This can degrade agent performance or bypass safety boundaries.

Content

Scanner excerpt · references/subscribing.md (reported line 236)May include surrounding context.

md
A subscription has three callbacks. Each one takes a listener and returns a function that removes it:

| Callback        | Listener arguments                 | Fires                                                                                                                                                                                                                                                                                                                            |
| --------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onChange`      | `snapshot: LiveQuerySnapshot<Row>` | After each state change, after each `changes` update while `live`, and when a new result is complete. Materialized subscriptions only.                                                                                                                                                                                           |
| `onStateChange` | `state: LiveQueryState`            | When the status changes.                                                                                                                                                                                                                                                                                                         |

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · references/subscribing.md (reported line 233)May include surrounding context.

md
A subscription has three callbacks. Each one takes a listener and returns a function that removes it:

| Callback        | Listener arguments                 | Fires                                                                                                                                                                                                                                                                                                                            |
| --------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onChange`      | `snapshot: LiveQuerySnapshot<Row>` | After each state change, after each `changes` update while `live`, and when a new result is complete. Materialized subscriptions only.                                                                                                                                                                                           |
| `onStateChange` | `state: LiveQueryState`            | When the status changes.                                                                                                                                                                                                                                                                                                         |

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · references/subscribing.md (reported line 235)May include surrounding context.

md
| Callback        | Listener arguments                 | Fires                                                                                                                                                                                                                                                                                                                            |
| --------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onChange`      | `snapshot: LiveQuerySnapshot<Row>` | After each state change, after each `changes` update while `live`, and when a new result is complete. Materialized subscriptions only.                                                                                                                                                                                           |
| `onStateChange` | `state: LiveQueryState`            | When the status changes.                                                                                                                                                                                                                                                                                                         |
| `onUpdate`      | `update: RawLiveQueryUpdate<Row>`  | With `type: "rows"` and `rows`, each `{ rowId, row }`, when a complete, authoritative result replaces the previous one. With `type: "changes"`, `changes` and `batch: LiveQueryBatchInfo` when committed transactions change the result. Each change is an `upsert` with a `rowId` and `row`, or a `remove` with only a `rowId`. |

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · references/subscribing.md (reported line 236)May include surrounding context.

md
| Callback        | Listener arguments                 | Fires                                                                                                                                                                                                                                                                                                                            |
| --------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onChange`      | `snapshot: LiveQuerySnapshot<Row>` | After each state change, after each `changes` update while `live`, and when a new result is complete. Materialized subscriptions only.                                                                                                                                                                                           |
| `onStateChange` | `state: LiveQueryState`            | When the status changes.                                                                                                                                                                                                                                                                                                         |
| `onUpdate`      | `update: RawLiveQueryUpdate<Row>`  | With `type: "rows"` and `rows`, each `{ rowId, row }`, when a complete, authoritative result replaces the previous one. With `type: "changes"`, `changes` and `batch: LiveQueryBatchInfo` when committed transactions change the result. Each change is an `upsert` with a `rowId` and `row`, or a `remove` with only a `rowId`. |

Listeners run in the order you add them, and one that throws doesn't stop the others. Each initial 
...[truncated 25 chars]

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · references/subscribing.md (reported line 243)May include surrounding context.

md
The status tells you how far to trust the rows:

| Status       | Meaning                                                                                                                                                                                      |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `connecting` | Waiting for a result: when it starts, including with `initialData` from a [server render](ssr.md), after a reconnect, and after renewing an expired sealed query. Rows you already have stay. |
| `live`       | The rows are authoritative and changes are streaming. It stays `live` while the server replaces the whole result.                                                                            |

Whitespace Padding

Medium
Category
Prompt Injection
Confidence
70% confidence
Finding

Large whitespace padding was detected (a block of blank lines or a long run of spaces). This can push injected instructions below or to the right of the visible area so a human reviewer never sees them while the agent still reads them. Manual review of the hidden content is recommended.

Content

Scanner excerpt · references/subscribing.md (reported line 249)May include surrounding context.

md
| `live`       | The rows are authoritative and changes are streaming. It stays `live` while the server replaces the whole result.                                                                            |
| `stale`      | The sealed query expired and the subscription is waiting for a renewed one. The rows are usable but may be out of date. Render them normally.                                                |
| `error`      | Automatic recovery has stopped. See [handle errors](#handle-errors).                                                                        |
| `closed`     | Closed by `unsubscribe()` or `client.close()`. It doesn't reopen.                                                                                                                            |

By default, subscriptions are materialized. The client keeps the rows and applies each update before `onUpdate` fires, so `getSnapshot()` in an update listener already includes it. If your code keeps its own rows, as TanStack DB does, pass `{ materialize: false }` for a raw subscription. It has the same callbacks except `onChange`, and no `getSnapshot()`. Keep the rows in a map keyed by `rowId`, replace them on each `rows` update and apply each `changes` update's upserts and removes:

Static analysis

No suspicious patterns detected.