Back to Home

Back to Index

“Security isn’t just about controls — it’s about choices.”

Attack Surface Reduction (ASR) is not a tool. It’s a mindset — and a development methodology. It calls for deliberate subtraction in how we design, build, ship, and maintain systems.

This section explains the foundational philosophy of ASR and its practical application in software engineering workflows. Together, they answer not just why we reduce exposure, but how we build systems that naturally minimize it.


1. The Subtraction Mindset

Most organizations react to breaches with more: more monitoring, more scanning, more dashboards, more tools. But these responses treat symptoms, not root causes. The real threat is excess — excess code, excess access, excess services, and excess complexity.

ASR flips this approach. Instead of managing complexity, we eliminate it:

  • Shut down unneeded services
  • Delete dormant credentials
  • Remove unused features
  • Avoid introducing fragile or bloated dependencies

“You don’t need to secure what you don’t expose.”

Example in practice: A team running 15 microservices discovers that 3 of them handle edge cases accounting for less than 2% of traffic. Rather than patching, monitoring, and maintaining all 15 services, they consolidate those three into the main services and decommission them. Attack surface reduced by 20% with zero feature loss.

Concrete action: Run docker ps or kubectl get pods in production. For each service, ask: “What happens if we turn this off for 24 hours?” If the answer is “probably nothing,” you’ve found your first candidate for removal.

This isn’t about moving fast and breaking things. It’s about moving deliberately and removing things.

Further reading:


2. Trust and Complexity Are Enemies

Modern systems trust too much, too easily. Your app trusts a CI job that trusts a cloud role that trusts an identity provider. Every new tool, abstraction, or library adds a new attack surface, a new trust boundary, and a new potential misconfiguration.

Transitive trust is the enemy. ASR promotes:

  • Explicit trust boundaries
  • Single-purpose roles and tokens
  • Zero implicit privileges
  • Flat systems over deep dependency chains

Real-world scenario: The SolarWinds breach succeeded partly because build systems had excessive permissions and trusted too many components. A compromised build dependency could inject code that was automatically trusted and distributed to 18,000+ customers.

Configuration example — Bad vs. Good IAM:

# BAD: Transitive trust, overly permissive
role: ci-deploy
permissions:
  - "*:*"  # Full access to everything

# GOOD: Explicit, scoped
role: ci-deploy-webapp
permissions:
  - s3:PutObject
    resource: "arn:aws:s3:::production-webapp/*"
  - cloudfront:CreateInvalidation
    resource: "arn:aws:cloudfront::123456789:distribution/E1234"

Prefer boring, understandable technology over trendy black-box stacks. If you can’t explain how a system works in three sentences, you probably can’t secure it either.

Further reading:


3. Intentional Development Practices

ASR-driven development doesn’t mean slow. It means intentional. Every dependency, every service, every API endpoint should be a conscious decision, not a default choice.

Code and Dependencies

  • Write clear, reusable internal code instead of importing dozens of npm packages
  • Choose one tool per function, not five alternatives
  • Build fewer moving parts so you can patch, monitor, and reason about them all

Example: Instead of pulling in a 50KB library to parse date strings, write 20 lines of code that handle your three specific date formats. You eliminate a dependency, understand the code completely, and have no transitive dependencies to worry about.

Development Environment Discipline

Too many environments have redundant SaaS tools, dozens of CI plugins, unused IDE extensions, and bloated local toolchains. ASR methodology promotes:

  • Minimal local environments
  • Version-locked build systems
  • Fewer but deeper integrations
  • Removing tools that require elevated access (root installers, kernel modules)

Audit your developer machine:

# macOS: See what's listening
sudo lsof -iTCP -sTCP:LISTEN -n -P

# Linux: Check installed packages
dpkg -l | wc -l  # How many packages?
apt list --installed | grep -i dev  # Development tools

Ask yourself: Do I know what each of these does? When’s the last time I used it?

Real incident: The event-stream npm package attack compromised thousands of projects because developers trusted a popular package without noticing a maintainer change. The malicious code targeted cryptocurrency wallets. This happened in a development dependency.

Further reading:


4. Context-Aware Minimalism

Side project? Experiment freely. But production applications demand respect for the long tail of maintenance, monitoring, upgrade risk, and supply chain attacks.

The principle: Don’t bring 12 vendors and 30 dependencies to solve a problem 3 teammates could handle with code you own.

This doesn’t mean reinventing every wheel. It means:

  • Critical systems: Minimize dependencies, prefer mature libraries, own your core logic
  • Internal tools: Can afford more experimentation, but still avoid bloat
  • Prototypes: Use whatever gets you to validation fastest

Decision framework:

System Criticality Dependency Tolerance Vendor Integration Monitoring Burden
Production (user-facing) Very low Minimal, vetted Full observability required
Internal tools Moderate Acceptable if reputable Basic monitoring
Prototypes/POCs High Acceptable Minimal

Example: A payment processing system should not use a new, trendy web framework with 200 dependencies. It should use boring, battle-tested technology that’s been around for a decade. Your internal admin dashboard? That has more flexibility.

Further reading:


5. Cultural Transformation

ASR isn’t just a technical practice — it’s a cultural shift. It requires teams to:

  • Say no more often — Not every feature request deserves implementation
  • Justify every addition — New services, new tools, new integrations need business cases
  • Celebrate deletions — Removing code is as valuable as writing it

Security improves most when simplicity becomes a habit, not a constraint.

How to shift culture:

  1. Make deletion visible: Track “lines of code removed” in sprint reviews
  2. Require justification: Before adding a new dependency, require a written explanation of why existing solutions won’t work
  3. Schedule cleanup sprints: Dedicate time to removing unused features, credentials, and services
  4. Reward simplicity: Recognize engineers who simplify systems, not just those who build new ones

Example: Basecamp deliberately limits features and says no to most requests. Their small team maintains a product serving millions because they keep the codebase and infrastructure lean.

Metrics that matter:

  • Number of active services (trend down)
  • Dependency count (trend down)
  • Time to understand a new codebase (trend down)
  • Number of IAM roles (trend down after cleanup)

Further reading:


6. The Bottom Line

“You don’t need 100% visibility if your footprint is 10% of what it used to be.”

ASR logic and methodology teach us that deliberate subtraction outperforms defensive sprawl. By focusing on what we don’t build, what we don’t expose, and what we don’t trust by default, we create systems that are inherently more secure.

The ASR promise:

  • Fewer breaches because there’s less to breach
  • Faster incident response because there’s less to investigate
  • Lower costs because there’s less to maintain
  • Better sleep because there’s less to worry about

Getting started checklist:

  1. ☐ Audit your running services and kill 20%
  2. ☐ Review your dependencies and remove unused ones
  3. ☐ Delete dormant user accounts and service credentials
  4. ☐ Turn off unused features and APIs
  5. ☐ Consolidate redundant tools and integrations
  6. ☐ Document what you removed and why

Build less. Expose less. Trust less. That’s how we regain control.

Further reading: