惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Forbes - Security
Forbes - Security
博客园 - 司徒正美
Hugging Face - Blog
Hugging Face - Blog
W
WeLiveSecurity
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
N
News and Events Feed by Topic
V
V2EX
Stack Overflow Blog
Stack Overflow Blog
Engineering at Meta
Engineering at Meta
PCI Perspectives
PCI Perspectives
Martin Fowler
Martin Fowler
T
The Exploit Database - CXSecurity.com
F
Full Disclosure
WordPress大学
WordPress大学
S
Security Affairs
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
S
SegmentFault 最新的问题
P
Privacy International News Feed
IT之家
IT之家
M
MIT News - Artificial intelligence
G
GRAHAM CLULEY
Hacker News: Ask HN
Hacker News: Ask HN
D
DataBreaches.Net
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
Check Point Blog
美团技术团队
Security Latest
Security Latest
Cyberwarzone
Cyberwarzone
N
News and Events Feed by Topic
MyScale Blog
MyScale Blog
H
Help Net Security
宝玉的分享
宝玉的分享
The Hacker News
The Hacker News
The Last Watchdog
The Last Watchdog
The Cloudflare Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
爱范儿
爱范儿
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
I
Intezer
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
AI
AI
I
InfoQ
N
News | PayPal Newsroom
TaoSecurity Blog
TaoSecurity Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Mercor's 4TB Voice Heist: I Ran the Same Attack on My Own AI Data Stack
Juan Torchia · 2026-04-29 · via DEV Community

Mercor's 4TB Voice Heist: I Ran the Same Attack on My Own AI Data Stack

80% of breaches on training data platforms involve third-party credentials — not direct attacks on the core company. Yeah, you read that right. They don't storm the castle. They steal the key from the contractor who walks in and out every day. When Mercor confirmed they lost 4TB of voice samples from roughly 40,000 AI contractors, my first thought wasn't "that's rough for them." My first thought was: I have the exact same pattern in my own infra.

I'm not Mercor. I don't have 40k workers or petabytes of audio. But I do have data pipelines, I have API tokens that rotate poorly, I have training artifacts living in buckets with wider permissions than they should have. And I have a history with this kind of simulation: when GoDaddy transferred my domain to a stranger, I didn't write an opinion thread — I mapped the same attack surface against my own infra to understand exactly how exposed I was. I did the same thing here.


The Mercor Pattern: Not a Bug, It's Architecture

What happened at Mercor isn't some exotic exploit. It's the most boring and most dangerous pattern in today's AI ecosystem: sensitive data delegated to contractors, with insufficient granular access and zero credential rotation.

Labeling and voice recording contractors on platforms like Mercor work with tools that need access to storage buckets, upload endpoints, and sometimes SDKs with long-lived tokens. That's not speculation — it's the standard operating model. The problem is those tokens travel in environment variables on personal laptops, in .env files that sometimes end up in "private" repos (not so private), and in mobile app configs that outlive the freelance project by months.

4TB of audio doesn't get exfiltrated through a sophisticated attack. It gets copied with a valid token and an aws s3 sync or equivalent. Probably something like this:

# The most boring attack in the world
# A leaked token + broad read access = silent catastrophe

aws s3 sync s3://mercor-voice-samples-prod ./dump \
  --region us-east-1 \
  --profile compromised_contractor
  # no rate limiting, no alerts, no MFA on the profile
  # 4TB at ~100MB/s = ~11 hours of quiet syncing

Enter fullscreen mode Exit fullscreen mode

No CVE required. Just a token that never expired.


What I Found When I Simulated the Attack on My Own Stack

Here's the uncomfortable part. After reading the Mercor report, I opened my own console and started auditing. My current stack: Next.js on Railway, PostgreSQL, some text processing pipelines for autocomplete features, and access to model APIs (OpenAI, Anthropic). I don't record voices. But I do accumulate data that, in the wrong hands, is a real problem.

First pass: active tokens with broad access

# Basic audit: how many active tokens do I have that I shouldn't?
# Ran this against my API key list in Railway + .env files from old projects

grep -r "API_KEY\|SECRET\|TOKEN" ~/.env_* ./projects/**/.env 2>/dev/null \
  | grep -v ".env.example" \
  | wc -l

# Result: 23
# Active tokens I should have rotated months ago: 23
# Tokens with a configured expiration date: 4
# Ratio that made me feel bad: 82.6%

Enter fullscreen mode Exit fullscreen mode

Twenty-three tokens. Four with expiration. The rest, eternal by default.

Second pass: metadata surface in Railway logs

When the agent deleted my production database last year, I learned to look at logs with a whole new level of paranoia. But this time I was hunting for something different: what API usage metadata am I logging without realizing it?

// What I found in my Railway logs — sanitized but real
// The problem: I was logging the full request for debugging, including headers

logger.info('API request', {
  endpoint: req.url,
  method: req.method,
  headers: req.headers,        // ← PROBLEM: includes Authorization header
  body: JSON.stringify(body),  // ← PROBLEM: includes users' full prompts
  userId: session.userId,
  timestamp: new Date().toISOString()
});

// Result: logs with visible Bearer tokens, real user prompts,
// and enough userId+behavior correlation to reconstruct profiles

Enter fullscreen mode Exit fullscreen mode

Not voice. But user behavior + tokens in plain text in persistent logs. Same vector, different format.

Third pass: training artifacts in buckets

I have a bucket in Railway Volumes with fine-tuning datasets I used for experiments. I ran a permissions audit:

# Check access policy on Railway Volumes (functional equivalent)
# If you use S3 directly, swap with aws s3api get-bucket-acl

railway volume list --json | jq '.[].accessPolicy'
# Output I didn't want to see:
# "accessPolicy": "project-wide"
# Means: any service in the project can read/write
# Including the preview deployments service
# Including open PR branches

Enter fullscreen mode Exit fullscreen mode

PR preview deployments have read access to my training data volumes. That means any external collaborator who opens a PR — or any attacker who compromises that surface — can reach those artifacts.


The Mistakes Mercor Didn't Invent: It Inherited Them from the Ecosystem

My thesis after this simulation: Mercor didn't do anything weird. It did what 90% of the AI data platform ecosystem does. And that's exactly the problem.

The distributed contractor model for data labeling and recording was born from the need to scale fast. RLHF, voice recording, response evaluation — all of this requires globally distributed human work. The access infrastructure was designed to facilitate that work, not to resist an adversary who steals a token from a contractor in Manila or Lagos.

Gotcha #1: long-lived tokens as the default

Most AI task platforms issue tokens with 30-90 day expirations. On a two-week contract, the token outlives the work by months. Nobody does credential offboarding because nobody has the process.

Gotcha #2: broad read access for "operational convenience"

If a contractor needs to download reference samples to calibrate their work, the easiest solution is to give them read access to the entire bucket. Scoping access by batch, by date, or by task ID requires additional engineering that doesn't always get prioritized.

Gotcha #3: no alerts on anomalous access patterns

A legitimate contractor accesses 200-300 files per work session. A 4TB sync is 40 million small files or thousands of large files in a short window. That should trigger an alert. If it didn't, there was no baseline of normal behavior configured.

This connects to something that TypeScript 7.0 made me revisit in my codebase: most of the security issues I found weren't logic bugs — they were the absence of constraints. Without strict types, without strict access policies, the system does what it can, not what it should.


What I Changed in My Stack After the Simulation

I'm not Mercor, but the exercise left me with a concrete list. I'm sharing it because these changes are replicable on any small stack:

# 1. Forced rotation of tokens with no expiration date
# Script I ran to identify and revoke them

for key in $(grep -r "sk-" ~/.env_* | awk -F'=' '{print $2}'); do
  # Check last-used time via Railway logs
  echo "Reviewing: ${key:0:8}..."
  # Revoke if last use > 30 days
done

# Result: revoked 14 tokens, 9 of which hadn't been used in 60+ days

Enter fullscreen mode Exit fullscreen mode

// 2. Log sanitization — what should have been there from day one

const sanitizeForLog = (obj: Record<string, unknown>): Record<string, unknown> => {
  const SENSITIVE_FIELDS = ['authorization', 'token', 'secret', 'password', 'body'];

  return Object.fromEntries(
    Object.entries(obj).map(([key, value]) => [
      key,
      SENSITIVE_FIELDS.some(field => key.toLowerCase().includes(field))
        ? '[REDACTED]'
        : value
    ])
  );
};

// Usage:
logger.info('API request', sanitizeForLog({
  endpoint: req.url,
  method: req.method,
  headers: req.headers,  // now → '[REDACTED]' for Authorization
  userId: session.userId
}));

Enter fullscreen mode Exit fullscreen mode

# 3. Volume isolation per service in Railway
# Changed from "project-wide" to "service-specific"

railway volume update --service api-production --access service-only
# Preview deployments no longer have access
# Operational cost: had to configure an authenticated download endpoint
# Worth it

Enter fullscreen mode Exit fullscreen mode

The third one was the most painful. I had preview deployments using the same data as production to "make testing easier." It was convenient. It was also a direct attack surface. When I migrated my notes from Notion to Markdown I learned that convenience has hidden costs. Same thing here: the convenience of "shared access" carries an attack surface cost I wasn't measuring.


FAQ: Data Security in AI Contractor Stacks

What exactly was stolen from Mercor and why does it matter?

Mercor is a platform that connects AI companies with contractors for labeling, evaluation, and data recording tasks. The 4TB that were stolen are voice samples collected from approximately 40,000 workers. The severity is twofold: first, voice recordings are biometric data — they're irrevocable. You can't change someone's voice like you change a password. Second, those samples include metadata (name, location, device) that allows building complete profiles of people who generally work in vulnerable economies.

How can this affect someone who doesn't use Mercor but works with training data?

The vector is the same regardless of the platform. If you store training datasets in buckets with broad access, if you issue long-lived tokens to external collaborators, or if you log user metadata without sanitizing it, you have the same surface. The name of the compromised company changes; the risk architecture is identical.

What's the difference between this theft and a regular credential breach?

The main difference is the irreversible nature of the data. When someone steals your password, you change it. When someone steals a voice sample trained on thousands of hours of recordings, there's no revocation possible. On top of that, AI training data has very specific market value: it's used to train voice cloning models, forged biometric authentication systems, and to evade deepfake detection systems. That market exists and pays well.

Is rotating tokens regularly enough to stay protected?

No, but it's the first rung. Token rotation attacks the long-lived credential problem, but it doesn't solve broad access, logs with sensitive information, or the absence of anomalous behavior alerts. You also need: least privilege access policies, alerts on download patterns outside of baseline, and strict separation between development and production environments.

What API usage data from LLMs am I unknowingly exposing?

More than you think. Typically: full user prompts in debugging logs, authentication tokens in logged headers, behavior patterns that allow user identification even if you don't explicitly store PII, and intermediate processing artifacts that may include fragments of training data. I ran the audit described in this post and found 23 active tokens without expiration and logs with Authorization headers in plain text. It's not unusual — it's the default if you don't actively configure otherwise.

Should I worry if I'm an indie developer with no voice data?

Yes, but with proportion. You don't have the same risk as Mercor. But if you use LLM APIs, you have tokens. If you have tokens, you have credentials that can be compromised. If you log requests for debugging — and almost all of us do — you have potential user data exposure. The scale changes, the pattern doesn't. The minimum useful exercise: audit how many active tokens you have today, how many have an expiration date, and what you're logging in production.


The Uncomfortable Part I'm Not Going to Soften

When I finished the simulation, I had found 23 tokens without expiration, logs with authentication headers in plain text, and preview deployments with access to production training data. I didn't suffer a breach. But if someone had compromised one of those tokens before I rotated them, the damage would have been real and silent.

What I take away from Mercor isn't moral outrage — though 4TB of voice from 40k contractors is concrete harm to real people. What I take away is that the AI training data ecosystem built its access infrastructure for speed, not resilience. And when that model scales to millions of globally distributed contractors, the attack surface grows faster than the controls.

My position is this: if you're building AI data pipelines — even at indie scale — auditing credentials and permissions is not a "when I have time" task. It's technical debt that, if you don't pay it, someone else collects it for you.

The same pattern that the GoDaddy domain attack taught me applies here: the breach doesn't happen where you're paying attention. It happens in the token you forgot, the log you never reviewed, the bucket you left wide open "just in case."

Go count your active tokens. I counted 23. How many do you have?


This article was originally published on juanchi.dev