Dev.to Security 🔐 Cybersecurity 👁 1 📖 2 min read

Leaked embeddings are leaked text: the RAG risk nobody checks

Most RAG security talk is about prompt injection. Here's a risk almost nobody checks: the embedding vectors themselves. Embeddings are not a one-way hash It's tempting to treat an embedding as a safe, anonymi

Most RAG security talk is about prompt injection. Here's a risk almost nobody checks: the embedding vectors themselves.

Embeddings are not a one-way hash

It's tempting to treat an embedding as a safe, anonymized fingerprint of your text. It isn't. Recent work (vec2text, Morris et al., 2023) showed you can invert an embedding back into much of its original text. The attack is simple in spirit: start from a guess, embed it, compare to the target vector, and iteratively edit the text until its embedding matches. Given the vector, the decoder reconstructs a large chunk of what you embedded, often near verbatim for short passages.

So an embedding is as sensitive as the source document it encodes. If your pipeline hands out raw vectors anywhere, it is leaking the content those vectors came from, even if the text never leaves the box.

What the leak actually looks like

The dangerous part is that it never looks like a breach. Here's a "helpful" debug response from a RAG API:

{
  "answer": "Our refund window is 30 days.",
  "debug": {
    "retrieved_chunks": [
      {
        "source": "internal/refund-policy.md",
        "embedding": [0.0123, -0.0917, 0.0442, 0.1131, -0.0075, 0.0881, -0.0210, 0.0559]
      }
    ]
  }
}

There's no obvious secret there, just a list of floats. But that embedding array can be inverted back into the chunk it came from. If that chunk was private, you just shipped it to the client in a field nobody thought to guard.

RAG pipelines expose vectors in more places than you'd think:

  • A debug or verbose mode that includes the embedding in the response
  • Logs that dump the query or chunk vector while troubleshooting
  • API metadata that returns the vector alongside the answer
  • A vector store or admin endpoint with weak access control

The fix is boring and effective

  • Never return raw embeddings to clients. Strip them from responses and debug output.
  • Keep vectors out of logs. Log an ID or a hash, not the vector.
  • Treat your vector store like a datastore full of sensitive text, because that is what it is. Access-control it.
  • Access-control any debug endpoint that can surface vectors.

How to check your own pipeline

The zero-effort version: grep your logs and captured API responses for long runs of floats.

grep -RnE '\[-?[0-9]+\.[0-9]+(, *-?[0-9]+\.[0-9]+){7,}' ./logs

If that finds anything a user or an attacker could reach, treat it like you found a password in there. Because functionally, you did.

I added a probe for exactly this to rag-redteam in v0.3. It asks a pipeline for its vectors a few different ways and flags any response that actually contains a raw embedding. It's one of seven probes that test the retrieval pipeline itself, not the model, for injection and leakage, and it runs as a CI gate:

pip install rag-redteam
rag-redteam run --target mypackage.my_rag:build --probes embedding_inversion

Repo and threat model: https://github.com/Srivatsa03/rag-redteam

Prompt injection gets all the attention, but your embeddings are quietly carrying the same text you were trying to protect. Check where they end up.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.