Skip to content

Auto Fix Engine

John Williams edited this page Mar 16, 2026 · 1 revision

Auto-Fix Engine

Philosophy

Last Mile's auto-fix engine generates suggestions, not mutations. Every patch is displayed to the developer for review — nothing is auto-applied. This is a deliberate design choice:

  1. Security tools should not modify code without human approval. A false positive that gets auto-fixed could break production.
  2. Context matters. A CORS wildcard might be intentional for a public API. The developer knows; the scanner guesses.
  3. Trust is earned. Until the false positive rate is provably <1%, auto-apply is irresponsible.

Fix Suggestions by Rule Type

Secret Detection Fixes

Pattern Fix
Hardcoded API key Move to environment variable, add to .gitignore
Database URL in code Use DATABASE_URL env var
Private key in repo Move to secrets manager, add *.pem to .gitignore
JWT secret in source Use JWT_SECRET env var

Example patch:

--- a/src/config.js
+++ b/src/config.js
@@ -3,1 +3,1 @@
-const API_KEY = 'sk-abc123def456';
+const API_KEY = process.env.OPENAI_API_KEY;

SAST Rule Fixes

Rule Fix
innerHTML Replace with textContent or add DOMPurify
CORS wildcard Replace * with specific origin(s)
eval() Refactor to avoid dynamic execution
HTTP URLs Replace http:// with https://
console.log Replace with structured logger call

Infrastructure Fixes

Finding Fix
No .gitignore Generate .gitignore from template (Node, Python, etc.)
No health endpoint Generate /health route stub
Docker runs as root Add USER node directive
No CI config Generate GitHub Actions workflow template
Missing lock file Run npm install to generate package-lock.json

Database Fixes

Finding Fix
No RLS Generate ALTER TABLE ... ENABLE ROW LEVEL SECURITY
Raw SQL Wrap in parameterized query helper
No migrations Generate migration directory scaffold

Patch Generator

The fix engine includes template generators for common scaffolding needs.

Dockerfile Template

When infra/no-dockerfile is detected:

FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
USER node
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "src/index.js"]

CI/CD Template (GitHub Actions)

When infra/no-ci is detected:

name: CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npm run lint
      - run: npm test

Health Endpoint Template

When infra/no-health-endpoint is detected:

// Express
app.get('/health', (req, res) => {
  res.status(200).json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Cloudflare Worker
if (url.pathname === '/health') {
  return new Response(JSON.stringify({ status: 'ok' }), {
    headers: { 'Content-Type': 'application/json' }
  });
}

.gitignore Template

When infra/no-gitignore is detected:

node_modules/
dist/
.env
.env.local
*.log
coverage/
.DS_Store

Framework-Aware Template Generation

The fix engine detects your framework and generates appropriate fixes:

Framework Detection Template Adjustments
Next.js next.config.js, pages/ or app/ dir Next.js-specific .gitignore, API route health check
Express express in package.json Express middleware patterns, helmet integration
Supabase @supabase/supabase-js in deps RLS policies, migration structure
Cloudflare Workers wrangler.toml Worker-specific health check, no Dockerfile
Fastify fastify in package.json Fastify plugin patterns

Human-in-the-Loop

The fix workflow is always:

Scanner finds issue
       │
       ▼
Fix engine generates patch
       │
       ▼
Patch displayed to developer
       │
       ▼
Developer reviews and decides
       │
  ┌────┴────┐
  ▼         ▼
Apply    Dismiss
(manual)  (reason logged)

Applying Fixes

# View all available fixes
last-mile fix .

# View fixes for a specific rule
last-mile fix . --rule sast/cors-wildcard

# Save patches to a file for review
last-mile fix . --output patches.diff

# Apply via standard tools (developer's choice)
git apply patches.diff

Why Not Auto-Apply?

  1. False positives exist. Every SAST tool has them. Auto-applying a false positive fix breaks working code.
  2. Context is king. Access-Control-Allow-Origin: * is wrong for a private API but correct for a public CDN endpoint.
  3. Rollback is hard. If an auto-fix breaks something in production, the developer didn't review it, doesn't understand it, and can't debug it quickly.
  4. Trust building. As the false positive rate decreases through community validation, auto-apply may become an opt-in feature for low-risk fixes (Phase 6+).

Clone this wiki locally