Lightweight, dependency-free fake of AWS Secrets Manager that speaks the real AWS JSON 1.1 wire protocol, so application code using @aws-sdk/client-secrets-manager can run against it with zero cost and zero side effects.
Key
Value
Port
4572
Protocol
AWS JSON 1.1 (X-Amz-Target: secretsmanager.<Operation>) over HTTP
Compatible client
@aws-sdk/client-secrets-manager (v3)
Size
~80 KB
Startup
< 100ms
State
In-memory, ephemeral, resettable
Quick Start
Start the server:
import { SecretsmanagerServer } from "./services/secretsmanager/src/server.js";
const server = new SecretsmanagerServer(4572);
await server.start();
// ... use it ...
await server.stop();
Connect with the real AWS SDK client:
import {
SecretsManagerClient,
CreateSecretCommand,
GetSecretValueCommand,
PutSecretValueCommand,
DescribeSecretCommand,
} from "@aws-sdk/client-secrets-manager";
const sm = new SecretsManagerClient({
region: "us-east-1",
endpoint: "http://127.0.0.1:4572",
credentials: { accessKeyId: "parlel", secretAccessKey: "parlel" },
});
// Create a secret
const { ARN } = await sm.send(
new CreateSecretCommand({ Name: "db/password", SecretString: "s3cr3t" }),
);
// Read it back
const { SecretString } = await sm.send(
new GetSecretValueCommand({ SecretId: "db/password" }),
);
console.log(SecretString); // "s3cr3t"
// Rotate the stored value (creates a new AWSCURRENT version; the old one
// becomes AWSPREVIOUS)
await sm.send(
new PutSecretValueCommand({ SecretId: "db/password", SecretString: "n3w-s3cr3t" }),
);
// Inspect metadata + version staging map
const meta = await sm.send(new DescribeSecretCommand({ SecretId: "db/password" }));
console.log(meta.VersionIdsToStages);
The SecretId parameter accepts either a bare secret name or a full ARN
(arn:aws:secretsmanager:us-east-1:000000000000:secret:db/password-aB3xZ9).
Wire protocol
Requests: POST / with header X-Amz-Target: secretsmanager.<Operation> and
Content-Type: application/x-amz-json-1.1. The body is the operation's JSON input.
SecretBinary is base64-encoded on the wire (the SDK handles encode/decode).
Timestamp fields (CreatedDate, DeletionDate, LastChangedDate, ...) are
epoch-seconds numbers; the SDK surfaces them as Date objects.
Success: 200 with the operation's JSON output.
Error: non-2xx with { "__type": "<Code>", "message": "<msg>" } plus an
x-amzn-errortype: <Code> header.
Implemented operations
All 23 operations exposed by @aws-sdk/client-secrets-manager are implemented.
Secret lifecycle
Operation
Notes
CreateSecret
Name validation, tags, KMS key id, replica regions, ClientRequestToken idempotency, rejects duplicate names and SecretString+SecretBinary together.
UpdateSecret
Updates description/KMS key; a new value creates a fresh AWSCURRENT version (old → AWSPREVIOUS).
This emulator faithfully replicates the API surface most application code and agents exercise. Anything below the supported lines is either an intentional design choice for a fast, zero-cost local emulator (✓ By design) or a candidate for a future release (⟳ Roadmap) — never a silent inaccuracy.
Legend: ✅ fully supported · ◐ accepted (stored, not strictly enforced) · ✓ by design · ⟳ on the roadmap.
Feature
Status
Secret CRUD (string + binary)
✅ Supported
Version staging (AWSCURRENT/AWSPREVIOUS/AWSPENDING + custom)
Copy these into your test.env (used by the bridge sidecar flow). Tokens are Parlel's seeded test credentials — any non-empty value is accepted by the emulator, so you rarely need to change them. Swap in real credentials only when pointing at the live service in prod.env.