Blog · ← All posts
Replit Agent Code Audit: What to Check Before You Publish
Last updated: October 2026 · 8 min read
Replit Agent doesn't just autocomplete, it runs commands, installs packages, edits files, and deploys. That agency is the point, and it's the risk: the agent makes dozens of security-relevant decisions per session (key storage, deserialization, input handling) that you'd normally make deliberately. Here's what to audit in its output before the app goes public.
1. Unsafe deserialization: pickle, yaml.load, marshal
Python agents love pickle for "save the session state" tasks. Unpickling data you didn't create is remote code execution, the object graph executes code at load time, no exploit chain required.
# VULNERABLE — unpickling user-supplied or network data import pickle state = pickle.loads(request.files['session'].read()) # FIXED — JSON for untrusted data, always import json state = json.loads(request.files['session'].read())
What our scanner does: the unsafe deserialization check class flags pickle.loads, yaml.load without a safe loader, and marshal on untrusted input. On Pro, the deserialization gadget chains advanced detector hunts the harder variant, chained gadgets across classes that naive scanners miss.
2. eval / exec on agent-built strings
Agents reach for eval when building "dynamic" behavior, calculators, rule engines, formula fields. Every one is code injection.
# VULNERABLE
result = eval(f"compute({user_expr})")
# FIXED — parse, don't execute
import ast, operator
# allow-list of operators only; reject everything else
result = safe_eval(user_expr) # ast-based, no builtins, no imports
What our scanner does: the eval usage check class flags eval/exec sinks, and taint tracking (Pro) proves whether user input actually reaches them.
3. SSTI: templates that evaluate user input
Flask/Jinja2 agents sometimes pass user content through render_template_string, a server-side template injection that escalates to RCE via {{ self.__init__.__globals__ }} traversal.
# VULNERABLE — user input becomes template source
return render_template_string(f"<h1>Hello {name}</h1>")
# FIXED — data stays data
return render_template("hello.html", name=name)
What our scanner does: the SSTI risk check class flags reflected input in template sources. Pro's advanced SSTI detector covers non-Jinja2 engines (Mako, Tornado, ERB, Handlebars server-side) that basic scanners ignore.
4. Secrets in the Repl
Replit has a Secrets manager, but the agent doesn't always use it. Hardcoded API keys in main.py are one accidental "make this public" away from exposure, and public Repls are exactly that.
What our scanner does: the secrets check class (32 patterns on Pro) flags key-shaped values in pasted code with per-secret blast radius and rotation runbooks.
5. Agent-specific: prompt-injection sinks and tool-call injection
Replit Agent apps increasingly are agents, chat interfaces, tool-using assistants, RAG over your docs. The new vulnerability classes live here: untrusted content (webpages, uploads, tool outputs) that steers the LLM into calling privileged tools, and retrieved documents that poison answers.
What our scanner does: three advanced detectors (Pro) map this surface: LLM prompt-injection sinks (untrusted text concatenated into prompts), insecure LLM output handling (model output rendered or executed without validation), and RAG poisoning (retrieved chunks influencing security decisions). See our LLM-threat pillar for the full breakdown.
6. SQL built from f-strings
Agents write f-string SQL constantly. One f"SELECT * FROM users WHERE name = '{name}'" is a full injection.
# VULNERABLE
cur.execute(f"SELECT * FROM users WHERE name = '{name}'")
# FIXED — parameterized, always
cur.execute("SELECT * FROM users WHERE name = %s", (name,))
What our scanner does: the SQL injection risk class flags concatenated queries; second-order injection (Pro) catches the stored-then-executed variant.
7. The deployed Repl itself
Replit deployments are public by default. Verify the live state: no .env served, headers present, no debug console exposed.
What our scanner does: the live-site audit runs headers, exposure (.env/.git probes), and links checks against your deployed URL.
8. The agent's shell access, and what it left on disk
Replit Agent doesn't just write code. It runs commands: pip install, database migrations, curl calls to test endpoints, chmod on files. Every command it ran is a security-relevant action you didn't personally take, and the artifacts linger.
Check three things. First, the shell history and any scripts the agent created to "test" things: we've seen agents write API keys into throwaway test scripts, run them, and leave the scripts in the project. Second, file permissions: an agent that hit a permission error will sometimes chmod 777 its way past it, and that stays. Third, the packages it installed while iterating. Agents install, uninstall, and reinstall libraries across a session; the final requirements.txt doesn't always match what's actually in the environment, and orphaned packages with known CVEs have a way of surviving the cleanup.
The practical version: ask the agent "list every shell command you ran this session and every file you created outside the main app." Then read that list like an auditor, not like the person who asked for the feature. You're looking for credentials in command arguments, keys written to temp files, and installs you didn't approve.
What our scanner does: the secrets class flags key material in pasted code including test scripts and config files; SlopSquat Shield (Pro) verifies the final dependency list against PyPI regardless of how it got there.
9. Changes the agent made that you never asked for
This is the Replit Agent failure mode with no equivalent in plain code generation. You asked for a feature. The agent, working autonomously across files, also "fixed" things: refactored a function you didn't mention, upgraded a library, changed a config value to make its tests pass. Each unrequested change is a diff you didn't review because you didn't know it happened.
The fix is procedural, not technical. Before every deploy, diff the project against the last known-good state and read every change the agent made that wasn't part of your request. Not skim. Read. Agents are helpful to a fault: they tidy, they modernize, they "improve" error handling by catching exceptions broadly. Every one of those helpful edits is a potential defect wearing a friendly comment.
We recommend teams treat agent sessions like junior-developer PRs with no description: assume nothing, verify everything, and never deploy a session's output without a full diff review. The agent did the typing fast. The review is where the security actually happens.
The checklist
- ☐ No
pickle.loads/yaml.loadon untrusted data - ☐ No
eval/execon user-influenced strings - ☐ No user input inside
render_template_string - ☐ All secrets in Replit Secrets, none hardcoded
- ☐ Agent/tool features: untrusted content never concatenated into prompts
- ☐ All SQL parameterized
- ☐ No credentials in agent-created test scripts or shell history
- ☐ Full diff reviewed, including changes the agent made unprompted
- ☐ Deployed URL: headers set,
.env404s
FAQ
My Repl is private, do I still need this?
Private today isn't private forever: Repls get shared, forked, and deployed publicly. Audit the code, not the current sharing setting.
Does the scanner understand Python agent frameworks?
The code checks cover Python broadly (deserialization, eval, SSTI, SQLi, taint), and the Pro advanced engine specifically targets agent patterns, prompt-injection sinks, tool-call injection, RAG poisoning, insecure LLM output handling.
What about the packages the agent installed?
SlopSquat Shield (Pro) verifies every import in your code live against PyPI, hallucinated, newborn, and typosquat packages get flagged with the real package the agent probably meant.
How is this different from Replit's built-in checks?
Built-in checks catch syntax and basic errors. This is a security audit: data-flow analysis, secret detection with blast radius, and 16 advanced detector families built for exactly the patterns AI agents generate.
Replit-specific risks the generic checklists skip
Replit Agent doesn't just write code — it wires up the deployment. That convenience creates findings that don't exist in a plain repo. First, secrets: Replit's Secrets panel is the right home for keys, but Agent-generated code sometimes falls back to hardcoded values or .env files that get committed when the repl is exported to GitHub. Check both the running repl and the exported repo.
Second, the database. Agent loves provisioning a database and writing raw queries against it, and those queries get the same string-concatenation treatment as everything else the model writes — parameterize them, and confirm the database credentials aren't baked into a connection string in code.
Third, the public URL. Every repl gets one, and Agent-generated apps sometimes ship with debug routes, database admin panels, or "test" endpoints still mounted. Before you share the link beyond your team, enumerate the routes and ask of each one: does this need to exist in production, and who can reach it?
Finally, treat the Agent's own chat history as sensitive. It contains your prompts, your schema, sometimes pasted keys. If you export or share the repl, assume the history goes with it and scrub accordingly.