Credential blast radius in single-node platforms
How far does an application compromise travel when the application holds database-owner, object-storage root, and platform-wide service credentials?
Single-node deployments are common in small software companies.
The application, database, object storage, reverse proxy, and background worker may all run on one host through Docker Compose. This can be a rational operating model. It is inexpensive, understandable, and often appropriate for an early product.
The primary risk is not consolidation by itself.
The risk appears when infrastructure consolidation becomes identity consolidation.
An application process that holds a database-owner credential, an object-storage root key, and a platform-wide internal token is no longer merely an application process. It has become an administrative control plane for the product.
If that process is compromised, the attacker inherits everything the process is authorized to do.
Start with the application compromise
Security discussions often focus on whether credentials are stored securely or likely to leak.
That matters, but it is only one half of the problem.
The more useful question is:
What authority does an attacker receive at the moment this process is compromised?
Assume an attacker gains code execution inside the request-serving application container.
Depending on the deployment, they may be able to read:
- Process environment variables
- Mounted secret files
- Application configuration
- Internal service tokens
- Database connection strings
- Object-storage credentials
- SMTP credentials
- Session-signing material
The next step is not to count the secrets.
It is to map the authority attached to each one.
Credential names are misleading
A variable named DATABASE_URL sounds ordinary. Its effective privileges may include:
- Reading every tenant
- Updating or deleting every record
- Creating or dropping tables
- Altering constraints
- Changing object ownership
- Creating additional database objects
- Disabling row-level controls
- Modifying audit records
An “S3 access key” may represent a bucket-scoped runtime identity.
It may also be the object-storage root credential, capable of:
- Reading every object
- Deleting every object
- Creating or deleting buckets
- Changing bucket policies
- Creating service accounts
- Re-enabling anonymous access
- Changing retention settings
- Deleting recovery copies
The security property is not the credential’s label.
It is the maximum authority reachable through that credential.
The dimensions of blast radius
I evaluate credential blast radius across several dimensions.
Data scope
Determine whether the identity can access:
- One object
- One project
- One tenant
- Every tenant
- Draft or unpublished content
- Deleted or historical records
- Authentication data
- Audit records
- Backup data
Action scope
Determine whether it can:
- Read
- Create
- Modify
- Delete
- Change policy
- Create further credentials
- Disable logging
- Alter retention
- Perform administrative operations
Persistence
Determine whether the attacker can use the credential to:
- Create another account
- Add a service credential
- Modify startup configuration
- Survive password rotation
- Survive session revocation
- Reappear after redeployment
Recovery impact
Determine whether the same identity can destroy both production data and its recovery copies.
This is one of the most important boundaries in the system.
A backup controlled by the compromised application is not independent recovery.
Detection and repudiation
Determine whether unusual activity produces a security event and whether the same compromised identity can alter or delete that evidence.
A credential with broad operational authority and control over its own audit trail creates both a prevention and an investigation problem.
A common single-node failure pattern
A compact platform may use:
Application container
├── database-owner credential
├── object-storage root credential
└── shared internal renderer token
The application may still have strong controls:
- Consistent tenant authorization
- Parameterized database queries
- Private internal networks
- File-signature validation
- Secure sessions
- A hardened reverse proxy
Those controls reduce the likelihood of an application compromise.
They do not reduce the post-compromise authority of the application identity.
Once the process is compromised, application-layer authorization is no longer the relevant boundary. The attacker is operating beneath it using service credentials.
This distinction matters when prioritizing remediation.
Preventive application controls and post-compromise containment solve different problems.
Why least privilege changes the outcome
Consider two versions of the same application compromise.
Broad administrative identities
The attacker receives:
- Database ownership
- Full object-storage administration
- A platform-wide internal token
- Access to local recovery data
Potential outcomes include:
- Cross-tenant data theft
- Platform-wide modification
- Destructive deletion
- Policy changes
- Persistent service credentials
- Recovery-copy destruction
- Tampering with operational evidence
Scoped runtime identities
The attacker receives:
- Only the DML operations required by the application
- Object operations restricted to the required production bucket
- No identity-management operations
- No bucket-policy changes
- No schema ownership
- No backup access
- Project-scoped internal credentials
The compromise remains serious.
However, the attacker may be unable to:
- Alter the database schema
- Administer object storage
- Create infrastructure identities
- Delete immutable backups
- Use one project’s renderer credential for another
- Rewrite independent audit records
Least privilege does not prevent compromise.
It changes the incident from unrestricted platform administration to a breach with enforceable boundaries.
A practical database role model
A small platform can separate database responsibilities without creating an unmanageable number of identities.
Owner role
The owner role:
- Has no interactive login
- Owns schema objects
- Is not present in application containers
- Is used only through controlled administrative or migration workflows
Migration role
The migration role:
- Is used only during approved deployments
- Can explicitly assume the owner role where required
- Is absent from request-serving processes
- Is rotated and controlled separately from runtime credentials
Runtime role
The runtime role:
- Performs the reads and writes required by the application
- Cannot create, alter, or drop schema objects
- Cannot manage roles
- Cannot bypass row-level controls
- Cannot grant itself additional privileges
Worker role
The worker role:
- Receives only the operations required for background processing
- Is separated from the web identity when its data access differs
- Cannot perform unrelated administrative actions
Backup role
The backup role:
- Has read-only access for the selected backup method
- Cannot modify production data
- Is stored outside the normal application runtime
- Does not grant the application access to recovery storage
The strongest acceptance tests are negative:
CREATE TABLEfails as the runtime roleALTER TABLEfailsDROP TABLEfailsCREATE ROLEfails- Access to unrelated databases fails
- Backup credentials cannot modify data
- Normal application operations continue to work
A role definition is only an intention until these boundaries have been tested.
A practical object-storage model
Object-storage responsibilities should also be separated.
Useful identities include:
- Runtime upload and retrieval
- Worker-side processing
- Administrative policy management
- Backup replication
- Restore operations
The runtime identity should not be able to:
- Change bucket policy
- Create arbitrary buckets
- Delete the production bucket
- Manage users
- Create service accounts
- Change retention controls
- Delete immutable backup history
As with database roles, verify the policy through negative tests rather than relying solely on the configuration document.
Internal service credentials need scope too
Internal tokens are often treated as harmless because they are not public user credentials.
A shared token can still create a large blast radius.
A platform-wide renderer credential may allow one internet-facing renderer process to access render data for every project.
Project-scoped credentials improve:
- Tenant attribution
- Rotation
- Revocation
- Detection
- Containment
- Incident analysis
A compromised renderer should not automatically become a read path into every tenant.
The same principle applies to workers, automation accounts, migration identities, and monitoring integrations.
Separate recovery from production authority
A backup is not independent when production credentials can delete it.
A defensible recovery system should use:
- A separate account
- Separate credentials
- Separate storage
- Versioning or immutability
- Encryption
- A retention policy
- Restore testing
The application should not possess the authority required to erase its own recovery history.
This boundary often reduces real business risk more than another isolated application-layer control.
Single-node does not have to mean single boundary
One physical host may still contain meaningful security boundaries:
- Separate containers
- Internal-only networks
- Dedicated service identities
- Unix-socket interfaces
- Read-only filesystems
- Off-box backup storage
- Off-box security logs
- Non-root processes
- Restricted administration paths
These controls do not make one host equivalent to a multi-account cloud environment.
A complete host compromise will still cross many local boundaries.
However, they materially reduce what an application-level compromise can achieve before the attacker reaches the host itself.
That distinction is operationally valuable.
The relevant question is not whether the architecture is perfectly isolated.
It is whether each compromise stage requires the attacker to cross another observable and enforceable boundary.
Closing thought
Credential architecture should be designed from the breach outward.
Do not ask only whether a secret is difficult to steal.
Ask what the system becomes when it is stolen.
A compact platform can remain operationally simple while separating runtime, migration, administration, audit, and recovery authority.
That separation is what turns a single compromised process from a platform-wide administrative breach into an incident with limits.