
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@abstraks-dev/aws-helpers
Advanced tools
AWS SDK helpers with caching and retry logic for Secrets Manager and SSM Parameter Store
AWS SDK helpers with caching and retry logic for Secrets Manager and SSM Parameter Store.
getSecret() patternsnpm install @abstraks-dev/aws-helpers
Install only what you need:
# For Secrets Manager
npm install @aws-sdk/client-secrets-manager
# For SSM Parameter Store
npm install @aws-sdk/client-ssm
import { getSecret } from '@abstraks-dev/aws-helpers';
// Get entire JSON secret
const config = await getSecret('app-config');
console.log(config.API_KEY, config.DB_URL);
// Extract specific key from JSON secret
const apiKey = await getSecret('app-config', 'API_KEY');
// Get plain text secret
const token = await getSecret('github-token');
import { createSecretsManagerHelper } from '@abstraks-dev/aws-helpers';
const secrets = createSecretsManagerHelper({
region: 'us-west-2',
cacheTTL: 5 * 60 * 1000, // 5 minutes (default)
maxRetries: 3, // Default
});
// First call fetches from AWS
const key1 = await secrets.getSecret('app-config', 'API_KEY');
// Second call uses cache (no AWS API call)
const key2 = await secrets.getSecret('app-config', 'API_KEY');
// Clear cache when secrets rotate
secrets.clearCache('app-config');
// Get cache statistics
const stats = secrets.getCacheStats();
console.log(stats); // { size: 2, entries: [...] }
import { getParameter } from '@abstraks-dev/aws-helpers';
// Get decrypted parameter
const dbUrl = await getParameter('/app/database-url');
// Get without decryption
const value = await getParameter('/app/config', { withDecryption: false });
import { createSSMHelper } from '@abstraks-dev/aws-helpers';
const ssm = createSSMHelper({ region: 'us-west-2' });
// Get multiple parameters efficiently
const params = await ssm.getParameters([
'/app/database-url',
'/app/api-key',
'/app/redis-url',
]);
console.log(params['/app/database-url']);
console.log(params['/app/api-key']);
Drop-in replacement for existing patterns:
// Before: Custom getSecret helper
import { getSecret } from './helpers/secrets.js';
// After: @abstraks-dev/aws-helpers
import { getSecret } from '@abstraks-dev/aws-helpers';
// Same API!
const secret = await getSecret('app-config', 'JWT_SECRET');
createSecretsManagerHelper(options)Creates a Secrets Manager helper with caching and retry logic.
Parameters:
options.region (string, optional): AWS region (default: AWS_REGION env var or 'us-west-2')options.cacheTTL (number, optional): Cache TTL in milliseconds (default: 300000 = 5 minutes)options.maxRetries (number, optional): Maximum retry attempts (default: 3)options.retryDelay (number, optional): Initial retry delay in ms (default: 100)Returns: Object with methods: getSecret, clearCache, getCacheStats
Example:
const secrets = createSecretsManagerHelper({
region: 'us-west-2',
cacheTTL: 10 * 60 * 1000, // 10 minutes
maxRetries: 5,
retryDelay: 200,
});
helper.getSecret(secretName, key)Retrieves a secret from AWS Secrets Manager with caching.
Parameters:
secretName (string, required): Name or ARN of the secretkey (string, optional): Key to extract from JSON secretReturns: Promise<string | object>
Behavior:
Example:
// JSON secret: {"API_KEY": "abc123", "DB": "mongodb://..."}
const fullConfig = await helper.getSecret('app-config');
// Returns: { API_KEY: 'abc123', DB: 'mongodb://...' }
const apiKey = await helper.getSecret('app-config', 'API_KEY');
// Returns: 'abc123'
// Plain text secret
const token = await helper.getSecret('github-token');
// Returns: 'ghp_abc123...'
helper.clearCache(secretName)Clears cached secrets.
Parameters:
secretName (string, optional): Secret name to clear (clears all if omitted)Example:
// Clear specific secret (including all keys)
helper.clearCache('app-config');
// Clear all cached secrets
helper.clearCache();
helper.getCacheStats()Returns cache statistics.
Returns: Object with size (number) and entries (array of strings)
Example:
const stats = helper.getCacheStats();
console.log(stats.size); // 3
console.log(stats.entries); // ['secret1:KEY1', 'secret2', 'secret3:KEY2']
createSSMHelper(options)Creates an SSM Parameter Store helper with caching and retry logic.
Parameters:
options.region (string, optional): AWS region (default: AWS_REGION env var or 'us-west-2')options.cacheTTL (number, optional): Cache TTL in milliseconds (default: 300000 = 5 minutes)options.maxRetries (number, optional): Maximum retry attempts (default: 3)options.retryDelay (number, optional): Initial retry delay in ms (default: 100)Returns: Object with methods: getParameter, getParameters, clearCache, getCacheStats
helper.getParameter(name, options)Retrieves a parameter from SSM Parameter Store with caching.
Parameters:
name (string, required): Parameter name or pathoptions.withDecryption (boolean, optional): Decrypt SecureString (default: true)Returns: Promise
Example:
const dbUrl = await helper.getParameter('/app/database-url');
const publicConfig = await helper.getParameter('/app/version', {
withDecryption: false,
});
helper.getParameters(names, options)Retrieves multiple parameters efficiently with caching.
Parameters:
names (string[], required): Array of parameter namesoptions.withDecryption (boolean, optional): Decrypt SecureString (default: true)Returns: Promise - Map of parameter names to values
Behavior:
Example:
const params = await helper.getParameters([
'/app/db-url',
'/app/api-key',
'/app/redis-url',
]);
console.log(params['/app/db-url']);
getSecret(secretName, key, options)Simple wrapper for one-off secret retrieval (no persistent cache).
Example:
import { getSecret } from '@abstraks-dev/aws-helpers';
const secret = await getSecret('app-config', 'API_KEY', {
region: 'us-west-2',
});
getParameter(name, options)Simple wrapper for one-off parameter retrieval (no persistent cache).
Example:
import { getParameter } from '@abstraks-dev/aws-helpers';
const value = await getParameter('/app/config');
const secrets = createSecretsManagerHelper({ cacheTTL: 5 * 60 * 1000 });
await secrets.getSecret('config', 'KEY'); // AWS API call
await secrets.getSecret('config', 'KEY'); // Cache (0ms)
await secrets.getSecret('config', 'KEY'); // Cache (0ms)
// After 5 minutes...
await secrets.getSecret('config', 'KEY'); // Fresh fetch from AWS
Performance Impact:
Considerations:
clearCache() after manual secret updatesThe package automatically retries transient errors with exponential backoff:
const helper = createSecretsManagerHelper({
maxRetries: 3,
retryDelay: 100, // Initial delay
});
// Retry delays: 100ms, 200ms, 400ms
// Total max wait: 700ms before giving up
ServiceUnavailableExceptionThrottlingExceptionInternalServiceErrorExceptionAccessDeniedException (permission issue)ResourceNotFoundException (secret/parameter doesn't exist)ValidationException (bad request)Why? These errors won't be fixed by retrying.
Before:
// helpers/secrets.js
import {
SecretsManagerClient,
GetSecretValueCommand,
} from '@aws-sdk/client-secrets-manager';
const client = new SecretsManagerClient({ region: 'us-west-2' });
export async function getSecret(secretName, key) {
try {
const command = new GetSecretValueCommand({
SecretId: secretName,
VersionStage: 'AWSCURRENT',
});
const response = await client.send(command);
const secretString = response.SecretString;
try {
const secretObj = JSON.parse(secretString);
return key ? secretObj[key] : secretObj;
} catch (e) {
return secretString;
}
} catch (error) {
console.error(`Error retrieving secret ${secretName}:`, error);
throw error;
}
}
After:
import { createSecretsManagerHelper } from '@abstraks-dev/aws-helpers';
export const secrets = createSecretsManagerHelper({ region: 'us-west-2' });
export const getSecret = secrets.getSecret.bind(secrets);
Or just replace imports:
// Before
import { getSecret } from './helpers/secrets.js';
// After
import { getSecret } from '@abstraks-dev/aws-helpers';
Benefits:
// Good: Single instance with shared cache
const secrets = createSecretsManagerHelper();
export const getSecret = secrets.getSecret.bind(secrets);
// Avoid: New instance every time (no cache benefit)
function getSecret(name, key) {
const helper = createSecretsManagerHelper();
return helper.getSecret(name, key);
}
// Production secrets (rotate monthly)
const secrets = createSecretsManagerHelper({
cacheTTL: 10 * 60 * 1000, // 10 minutes
});
// Development secrets (rotate frequently)
const secrets = createSecretsManagerHelper({
cacheTTL: 60 * 1000, // 1 minute
});
// High-security (no caching)
const secrets = createSecretsManagerHelper({
cacheTTL: 0, // Always fetch fresh
});
// After rotating secret in AWS console
secrets.clearCache('app-config'); // Force fresh fetch
// Good: Single API call
const params = await ssm.getParameters(['/app/db', '/app/key', '/app/url']);
// Avoid: Multiple API calls
const db = await ssm.getParameter('/app/db');
const key = await ssm.getParameter('/app/key');
const url = await ssm.getParameter('/app/url');
const stats = secrets.getCacheStats();
console.log(`Cache size: ${stats.size}`);
console.log(`Cached entries: ${stats.entries.join(', ')}`);
// Log in CloudWatch for monitoring
Cause: Missing peer dependency.
Solution:
npm install @aws-sdk/client-secrets-manager
Cause: Lambda execution role lacks permissions.
Solution: Add IAM policy:
{
"Effect": "Allow",
"Action": ["secretsmanager:GetSecretValue"],
"Resource": "arn:aws:secretsmanager:REGION:ACCOUNT:secret:SECRET_NAME-*"
}
Cause: Secret doesn't exist or wrong name/region.
Solution:
aws secretsmanager list-secretsCause: Too many AWS API calls.
Solution: Increase cache TTL:
const secrets = createSecretsManagerHelper({
cacheTTL: 10 * 60 * 1000, // Increase from 5 to 10 minutes
});
Cause: Cache still has old value.
Solution:
// Clear cache after rotation
secrets.clearCache('app-config');
// Or reduce cache TTL for frequently-rotated secrets
const secrets = createSecretsManagerHelper({
cacheTTL: 60 * 1000, // 1 minute
});
| Operation | Without Cache | With Cache | Improvement |
|---|---|---|---|
| getSecret (first call) | 50-100ms | 50-100ms | - |
| getSecret (cached) | 50-100ms | <1ms | 50-100x faster |
| API calls (100 requests) | 100 | ~2-5 | 20-50x fewer |
| Cost (1M requests) | $400 | $8-20 | 20-50x cheaper |
Note: Actual performance depends on AWS region, network latency, and secret size.
MIT
FAQs
AWS SDK helpers with caching and retry logic for Secrets Manager and SSM Parameter Store
We found that @abstraks-dev/aws-helpers demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.