What red teams look for - before vulnerabilities reach production
Most vulnerabilities I exploit during VAPT were already visible in pull requests.
They weren't hidden. They weren't zero-days. They weren't advanced.
They were approved during code review because:
- The change worked
- Tests passed
- Nobody asked the security questions
From a red-team perspective, PR reviews are the last strong security gate before code reaches production.
This article is blunt on purpose.
Below are the exact security checks I mentally run when reviewing code, because these are the same patterns I exploit later.
1. Authentication & Authorization Changes
Red-team question:
Does this change allow someone to do something they couldn't do before?
What developers miss
- New endpoints added without authentication
- Role checks added only in the UI
- Admin logic hidden behind client-side flags
What I look for in PRs
- Every new route → where is auth enforced?
- Are role checks server-side?
- Are permissions inferred from client input?
Practical Example - The "Hidden" Admin Route
PR diff:
// Added new route for dashboard statistics
app.get('/api/stats', (req, res) => {
return db.getStats(); // ❌ Missing authentication middleware
});The exploit:
I don't need a login. I just curl /api/stats.
If the developer forgot requireAuth or @UseGuards(AuthGuard), I win.
The fix:
app.get('/api/stats', requireAuth, requireAdmin, (req, res) => {
...
});Red-team reality: If auth logic changes in a PR, I read it first.
2. Client-Controlled Data Crossing Trust Boundaries
Red-team question:
Is the server trusting something the client controls?
Common examples
isAdmin,role,price,userId- Hidden fields added to JSON payloads
- Frontend-only validation
What to check
- Does the server recompute sensitive values?
- Are IDs derived from session, not request body?
- Are defaults safe?
Practical Example - Mass Assignment
PR diff:
// Update user profile
app.post('/update-profile', (req, res) => {
const user = db.find(req.session.id);
user.update(req.body); // ❌ BLIND TRUST
user.save();
});The exploit: I intercept the request and send:
{
"name": "Hacker",
"role": "admin",
"is_verified": true
}The backend blindly updates everything.
Red-team reality: If you trust the client, you trust the attacker.
3. Input Validation & Deserialization
Red-team question:
What happens if this input is malformed, oversized, or unexpected?
Red flags in PRs
JSON.parse()on user input- Direct deserialization into models
- No size or depth limits
What to verify
- Schema validation exists
- Unknown fields are rejected
- Size and depth limits enforced
Practical Example - Prototype Pollution
PR diff:
function mergeSettings(target, input) {
for (let key in input) {
target[key] = input[key];
}
}The exploit:
{
"__proto__": {
"isAdmin": true
}
}This pollutes the global object prototype.
Red-team reality: I will throw garbage at your parser until it breaks or gives me access.
4. Outbound HTTP Requests (SSRF Alert)
Red-team question:
Can I control where the server sends requests?
High-risk changes
- URL fetchers
- Webhooks
- Import-from-URL features
- Preview / metadata fetch logic
What to check
- Is the destination allow-listed?
- Are internal IPs blocked at the network layer?
- Are redirects controlled?
Practical Example - Preview Feature
PR diff:
def get_preview(url):
return requests.get(url).content # ❌ DangerousThe exploit: I submit:
http://169.254.169.254/latest/meta-data/The server returns cloud credentials, not a preview.
Red-team reality:
If I see axios.get(req.body.url), I'm already inside your cloud.
5. Secrets, Tokens & Configuration Files
Red-team question:
Did this PR accidentally ship credentials?
Common mistakes
.envchanges- Temporary debug secrets
- Tokens logged "just for testing"
Practical Example - Hardcoded Key
PR diff:
// TODO: Remove before prod
const STRIPE_KEY = "sk_live_51Mz...";Even if deleted later, it's in git history forever.
The fix: Use environment variables or a secrets manager.
Red-team reality: Secrets leak → lateral movement → persistence.
6. Error Handling & Debug Output
Red-team question:
What does the app reveal when something breaks?
Practical Example - Verbose Errors
catch (SQLException e) {
return Response.status(500).entity(e.getMessage()).build();
}The exploit: Trigger an error → get DB type, table names, schema info.
Red-team reality: Error messages are free reconnaissance.
7. Logging & Audit Gaps
Red-team question:
If I abuse this feature, will anyone notice?
Practical Example - Silent Delete
app.delete('/user/:id', isAdmin, (req, res) => {
db.deleteUser(req.params.id);
res.send("Deleted");
});No actor. No timestamp. No trail.
The fix:
logger.info("User deleted", {
target_id: req.params.id,
actor_id: req.user.id,
timestamp: now()
});Red-team reality: Silent abuse beats loud exploits.
8. Dependency Changes & Supply Chain Risk
Red-team question:
What new code just entered your system indirectly?
Practical Example - Typosquatting
"dependencies": {
"cross-env": "^7.0.0",
"eletron": "^12.0.0"
}An attacker publishes eletron with a malicious post-install script.
Red-team reality: I don't need your code if I control your dependency.
9. CI/CD & Infrastructure-as-Code Changes
Red-team question:
Did this PR weaken your pipeline security?
Practical Example - Dangerous Workflow
on: pull_request_target
jobs:
test:
runs-on: self-hosted
steps:
- run: npm install && npm testA forked PR can execute attacker-controlled code with secrets.
Red-team reality: Pipeline compromise → production compromise.
10. Feature Flags, Debug Code & Bypasses
Red-team question:
What happens if this flag is flipped?
Practical Example - Temporary Bypass
if (req.query.debug === 'true' || checkAuth(req)) {
// Allow access
}Someone forgets to remove it. Now auth is optional.
Red-team reality: Temporary code becomes permanent attack surface.
The Red-Team PR Security Checklist (Save This)
Before approving any PR:
- Does this change affect auth or permissions?
- Is any client input trusted by the server?
- Are outbound requests introduced?
- Could this leak secrets or sensitive data?
- Are errors and logs safe?
- Does this add new dependencies?
- Does this touch CI/CD or infrastructure?
- Is any debug or bypass logic present?
If one answer is unclear, the PR needs another look.
Conclusion
Most vulnerabilities are not hacked in. They are:
- Reviewed
- Approved
- Deployed
Red teams don't magically break systems. We follow the paths code reviews allowed.
If you want fewer VAPT findings and fewer incidents:
Make security part of PR reviews - not postmortems.
Follow me for weekly red-team writeups, VAPT case studies, and practical secure-development guides. Connect with me on LinkedIn and GitHub.