Overview
Security vulnerabilities often slip through code reviews—incorrect API usage, hardcoded credentials, or insecure patterns can lurk undetected for months. This automation scans your codebase daily to catch these issues before they become breaches.
What it does:
- Scans your codebase on a schedule (daily, weekly, or monthly)
- Identifies common vulnerabilities (SQL injection, XSS, auth flaws, hardcoded secrets)
- Creates Linear tickets with severity ratings for each issue
- Optionally generates PRs with automated fixes
Quick Start
- Navigate to Automations in your Tembo dashboard
- Click Templates Library
- Install the “Security Vulnerability Scan” template
- Configure your repository and schedule
- Enable Linear and/or Slack integrations
How It Works
On each scheduled run, the automation:
- Clones the repository — Gets the latest code from your main branch
- Scans for vulnerabilities — Analyzes code patterns against known security issues
- Categorizes findings — Assigns severity levels (Critical, High, Medium, Low)
- Creates tickets — Opens Linear issues with details and remediation steps
- Generates fixes — Optionally creates PRs to fix identified issues
The scanner catches real issues like using jwt.decode() instead of jwt.verify()—a common mistake that bypasses signature verification entirely.
Configuration
Basic Setup
Trigger: Schedule (daily recommended)
Prompt Template:
Perform a security vulnerability scan on the codebase.
## Scan Categories
Check for these vulnerability types:
### Injection Flaws
- SQL injection (string concatenation in queries)
- Command injection (shell execution with user input)
- LDAP injection
- XPath injection
### Authentication Issues
- Hardcoded credentials or API keys
- Weak password requirements
- Missing rate limiting on auth endpoints
- JWT decode vs verify confusion
- Session fixation vulnerabilities
### Cross-Site Scripting (XSS)
- Unescaped user input in HTML output
- innerHTML with user data
- Missing Content-Security-Policy headers
### Sensitive Data Exposure
- Secrets in code or config files
- Sensitive data in logs
- Missing encryption for PII
- Exposed stack traces in production
### Security Misconfiguration
- Debug mode enabled
- Default credentials
- Unnecessary features enabled
- Missing security headers
## For Each Vulnerability Found
1. Identify the file and line number
2. Classify severity:
- Critical: Actively exploitable, data breach risk
- High: Exploitable with some effort
- Medium: Requires specific conditions
- Low: Minor issue or defense-in-depth
3. Create a Linear ticket with:
- Title: [Severity] [Vulnerability Type] in [file]
- Description: What's wrong and how to exploit it
- Remediation: Step-by-step fix instructions
- Label: "security", severity level
4. If auto-fix is enabled:
- Generate a fix for the vulnerability
- Create a PR with the fix
- Link the PR to the Linear ticket
MCP Servers Needed: GitHub, Linear (optional), Slack (optional)
Vulnerability Examples
JWT Decode vs Verify
The Issue:
// VULNERABLE: decode() doesn't verify the signature
const payload = jwt.decode(token);
The Fix:
// SECURE: verify() checks the signature
const payload = jwt.verify(token, process.env.JWT_SECRET);
SQL Injection
The Issue:
// VULNERABLE: String concatenation allows injection
const query = `SELECT * FROM users WHERE id = '${userId}'`;
The Fix:
// SECURE: Parameterized query
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);
Hardcoded Secrets
The Issue:
// VULNERABLE: Secret in source code
const apiKey = 'sk-live-abc123xyz789';
The Fix:
// SECURE: Environment variable
const apiKey = process.env.API_KEY;
XSS via innerHTML
The Issue:
// VULNERABLE: User input directly in HTML
element.innerHTML = userComment;
The Fix:
// SECURE: Use textContent or sanitize
element.textContent = userComment;
// Or use DOMPurify for rich content
element.innerHTML = DOMPurify.sanitize(userComment);
Customization Options
Severity-Based Routing
Route findings based on severity:
For Critical vulnerabilities:
- Create Linear ticket with Urgent priority
- Post to #security-alerts immediately
- Tag the security team lead
- Generate fix PR automatically
For High vulnerabilities:
- Create Linear ticket with High priority
- Include in daily security digest
For Medium/Low vulnerabilities:
- Create Linear tickets
- Include in weekly security report
Focus Areas
Customize what the scanner looks for:
API-Focused Scan:
Focus on API security:
- Authentication bypass opportunities
- Authorization flaws (IDOR, broken access control)
- Rate limiting gaps
- Input validation on all endpoints
- Proper error handling (no stack traces)
Frontend-Focused Scan:
Focus on client-side security:
- XSS vulnerabilities
- CSRF protection
- Sensitive data in localStorage/cookies
- Third-party script security
- Content Security Policy headers
Dependency Scan:
Check third-party dependencies:
- Known vulnerabilities in packages (CVEs)
- Outdated packages with security patches
- Unnecessary dependencies that increase attack surface
- License compliance issues
Exclude False Positives
Reduce noise from known safe patterns:
Ignore these patterns:
- Test files (*.test.js, *.spec.ts)
- Mock data with fake credentials
- Documentation examples
- Intentionally vulnerable code in /security-training/
Known false positives to skip:
- The API key in config.example.js is a placeholder
- The hardcoded password in seed.js is for local dev only
Example Linear Ticket
Here’s what an auto-generated security ticket looks like:
## [High] JWT Signature Bypass in auth/verify.js
### Summary
The authentication middleware uses `jwt.decode()` instead of
`jwt.verify()`, which skips signature verification entirely.
An attacker could forge tokens with arbitrary payloads.
### Location
- File: `src/auth/verify.js`
- Line: 23
- Function: `verifyToken()`
### Impact
- Severity: High
- CVSS Score: 8.1
- Exploitability: Easy (no special tools required)
### Proof of Concept
An attacker can create a forged token:
1. Base64 encode a custom payload with admin: true
2. Use any signature (it won't be checked)
3. Access admin endpoints
### Remediation
Replace `jwt.decode()` with `jwt.verify()`:
```javascript
// Before (vulnerable)
const payload = jwt.decode(token);
// After (secure)
const payload = jwt.verify(token, process.env.JWT_SECRET);
References
---
## Tips for Better Results
### 1. Start with High-Severity Only
Don't overwhelm your team with low-severity issues:
```text
For the first month, only report Critical and High severity issues.
Once those are addressed, expand to Medium severity.
2. Provide Codebase Context
Help the scanner understand your architecture:
Our security model:
- All API routes require authentication via JWT
- Admin routes additionally require role: "admin"
- File uploads are stored in S3, not locally
- We use Prisma ORM which prevents SQL injection
- Passwords are hashed with bcrypt (12 rounds)
3. Schedule Smart
Choose the right frequency:
- Daily: High-security applications (finance, healthcare)
- Weekly: Most production applications
- On PR: Critical paths (auth, payments)
Monitor your security posture over time:
Include in the weekly report:
- New vulnerabilities found this week
- Vulnerabilities fixed this week
- Open vulnerabilities by severity
- Average time to remediation