Workload-Aware Credential Capabilities
A Git-native, runtime security architecture for least-privilege, secretless application access — design proposal & evaluation plan
Abstract
Almost every modern application leans on credentials it does not actually need to own. It calls an API with a key it was given at startup, keeps a database password alive for the whole process, and holds on to cloud credentials that could sign for far more than the one operation being performed. We encrypt these secrets at rest, centralize them in vaults, and inject them at deploy time — and yet the architectural problem survives all of it: an application routinely ends up permanently possessing a credential it only needed for a narrowly defined operation.
This paper is a design proposal for a workload-aware credential capability layer: an open-source architecture that separates credential storage from workload identity, authorization, and credential use. The organizing principle is simple to state and hard to build well — an application should be able to use a credential without permanently owning it.
The design has two planes. A control plane manages identities, policy, resource metadata, and audit. A data plane — implemented as a local agent, a sidecar, or an embedded runtime depending on deployment size — enforces policy locally, resolves credentials, and brokers cryptographic operations. The control plane is deliberately kept out of the hot path of ordinary operations.
The system supports a staged progression. A compatibility mode returns the raw secret when an existing SDK insists on it. A stronger mode brokers operations such as HMAC signing or request signing so the credential never enters application code. Existing infrastructure is treated as an adapter layer rather than a replacement: SPIFFE/SPIRE for workload identity, GitHub OIDC for CI, and KMS/HSM or OpenBao for key authority all slot in behind one protocol.
This is an architecture and evaluation plan, not a claim of measured results. Nothing here has been benchmarked yet; the evaluation methodology is defined so that the prototype can be tested honestly when it exists. The claim being proposed for that future test is narrow: that workload-bound, operation-scoped, short-lived authorization measurably reduces persistent credential exposure without making day-to-day development impractical.
Keywords
least privilege, secrets management, workload identity, capability-based security, credential brokering, zero trust, DevSecOps, Git-native configuration
I. Introduction
A single modern application talks to a lot of services. Stripe, GitHub, AWS or GCP, a database, Redis, an email provider, a couple of internal APIs — and nearly every one of those integrations is authenticated by a credential. The practical problem was never that credentials exist; applications need them. The problem is that credentials keep becoming persistent artifacts — parked in a repository, baked into an image, copied into a dozen environments, valid for months or years after their one intended use.
A developer writes STRIPE_API_KEY=sk_live_... into an env file and commits it. From there the secret propagates into git history, CI caches, container registries, backups, and logs. OWASP's guidance on secrets management catalogues exactly this failure: API keys, database credentials, and signing material end up embedded in source code and configuration, and the recommended mitigations — least privilege, rotation, expiration, auditing — are all things that must be operated, continuously, by people who are already overloaded.
I want to separate two questions that usually get merged:
- Can an unauthorized party recover a stored secret? (Encryption answers this.)
- Is a workload even allowed to use that secret, for that operation, right now? (Encryption does not answer this.)
This proposal is built on the observation that these are different security questions, and that they should be answered by different parts of the system. Encryption protects the secret while it is stored. Workload identity establishes who is asking. Policy decides what that workload may do. A short-lived capability scopes when it may do it. And a broker makes it possible to perform the operation without handing the credential to the application at all.
The hoped-for contributions, in plain terms:
- A Git-native transition path. A protected resource starts as an encrypted, commit-safe artifact and becomes runtime authorization without developers manually decrypting files.
- A separation that can be reasoned about. Resource, credential, capability, and operation are distinct objects with distinct lifecycles.
- A credentialless destination. Compatibility with existing SDKs matters, but the architecture is designed so the preferred end state is brokered operations —
sign(),request(),proxy()— rather thanget_secret().
II. Background & Related Work
This design does not claim that encrypted Git secrets, workload identity, secret leasing, or credential brokering are new. Each exists, in production, today. What is missing is a unified abstraction that connects Git-native protected resources to workload-bound, operation-scoped runtime authorization with a realistic migration path.
SOPS encrypts YAML, JSON, ENV, INI, and binary files and integrates with AWS KMS, GCP KMS, Azure Key Vault, age, and PGP. It is the current best answer for "encrypted secrets that can live in a repo." What it does not do is bind those secrets to workload identity or scope their runtime use.
git-crypt provides transparent file encryption inside a repository, so encrypted files sit alongside source code. Its own documentation is admirably frank about the limits — metadata leakage and the near-impossibility of revoking access to history that was already decrypted for past collaborators.
OpenBao (and the Vault line it descends from) provides identity-aware secrets management and a Transit engine that performs encryption, signing, and HMAC operations without storing the data being processed — a real precedent for delegated cryptography.
SPIFFE/SPIRE standardizes workload identity: SPIFFE IDs, SVIDs, and a local Workload API that lets a process retrieve verifiable identity without shipping another secret around. This is exactly the identity layer this design wants to consume rather than reinvent.
Infisical demonstrates that credential brokering is practical, not theoretical — its agent attaches credentials at a broker/proxy boundary so agents and services perform operations without holding the underlying values.
So the honest gap statement is not "nobody has built these pieces." It is that each tool specializes in one layer — SOPS in storage, SPIFFE in identity, OpenBao in crypto services, Infisical in proxying — and the workload that needs least privilege end to end is left to stitch them together itself. This proposal is for the missing layer: one capability abstraction spanning storage, identity, policy, and use.
III. The Problem
The research question that drives the project:
Can applications use privileged external credentials while minimizing persistent credential exposure and avoiding the unnecessary transfer of raw credentials into application processes — without wrecking the developer workflow?
Underneath that question sit five concrete failure modes this design targets:
- Persistent storage. Credentials sit in plaintext in repos, configs, and build artifacts.
- Environment confusion. The same credential silently serves development, staging, and production, so a leak in the weakest environment is a production breach.
- Excessive possession. An application holds a full credential when it only needs to sign one kind of message or make one class of request.
- Long-lived authorization. Static credentials stay valid for months or years, so a single exposure has an enormous window.
- Runtime compromise. Even perfectly protected at rest, a credential that reaches an application process is recoverable if that process is compromised.
The proposal addresses the first four directly and mitigates the fifth by making the credentialless path the preferred one. Two hypotheses follow, which the prototype is designed to test:
- H1 (exposure): If privileged operations can be brokered, an application can obtain the result of the operation without possessing the credential.
- H2 (overhead): If authorization is enforced locally through short-lived leases rather than a control-plane round trip per operation, the added latency and availability risk stay within practical bounds.
IV. Threat Model & Non-Goals
The design is evaluated against explicit adversaries rather than vague "hackers."
Assets: plaintext and encrypted credentials, workload identity material, capabilities, encryption keys, policies, audit records, and provider credentials.
Adversaries: a repository thief; a malicious repository contributor; a malicious CI workflow; a compromised staging workload; a compromised but authorized application; a fully compromised host; a malicious administrator; a compromised control plane; a compromised runtime dependency (including the SDK itself).
Trusted components must be declared per deployment rather than assumed globally: the cryptographic library, the identity issuer, the configured KMS/HSM, and the OS security boundary. The whole point of listing them is that different deployments may legitimately trust different sets.
The security goals are deliberately narrow and measurable:
- G1. Repository compromise alone does not yield usable production credentials.
- G2. Unauthorized workload identities receive nothing.
- G3. Capabilities are scoped by principal, resource, operation, audience, and expiry.
- G4. Brokered operations do not expose the underlying credential to application code.
- G5. Plaintext credentials are not intentionally persisted to disk during normal operation.
- G6. Access attempts are auditable without ever logging the credential itself.
And the non-goals are stated just as clearly, because a security architecture that overclaims is a liability:
- N1. A fully compromised application that legitimately received a raw credential is not protected. This is why the credentialless path exists, and why compatibility mode is labeled compatibility.
- N2. Full host/root compromise is out of scope; the response to that threat is moving operations into a stronger trust domain (KMS/HSM, confidential computing), not pretending the local agent can hold the line.
- N3. Universal revocation of externally issued credentials is impossible; the system can revoke its own capabilities and guide external rotation.
- N4. Granularity cannot exceed what the external provider itself supports — brokering cannot make an all-powerful API key less powerful outside the operations the broker understands.
V. Architecture
The architecture has two planes and one rule: the control plane is not on the hot path.
Control plane
Owns identity registration, resource metadata, policy, capability issuance, lease management, and audit. A workload interacts with it rarely — at bootstrap and renewal — never per operation.
Data plane
Owns local enforcement: validating capabilities, resolving credentials, performing cryptographic operations, secure caching, and brokered provider requests. It runs as a local agent, a sidecar, or an embedded runtime depending on the deployment.
Git / CI / Config
|
secure:// references
|
v
+-------------------------+
| CONTROL PLANE |
| identity | policy |
| capability | lease |
| metadata | audit |
+------------+------------+
|
short-lived grant
|
v
+-------------------------+
| DATA PLANE |
| agent/sidecar/runtime |
| identity adapter |
| local enforcement |
| cache | crypto | broker|
+------------+------------+
|
authenticated IPC
|
v
+-------------------------+
| APPLICATION |
| secret() sign() |
| request() |
+------------+------------+
|
v
External API
Why the agent is optional
A developer should not have to run a background service to read encrypted config. So the deployment spectrum is explicit: local mode is CLI plus SDK; a production server adds an optional agent; Kubernetes and high-security environments run the agent as a sidecar or node broker. The same protocol underlies all three — the agent is an enforcement optimization, not a requirement.
Identity is an adapter, not an invention
The system consumes existing identity mechanisms: SPIFFE/SPIRE where available, GitHub OIDC in CI, cloud workload identity on AWS/GCP/Azure, Kubernetes service identity, or mTLS. A workload appears as something like spiffe://acme.example/prod/payments/api rather than as APP_ID plus APP_TOKEN — because the second design just creates another secret.
Resources, credentials, capabilities
A protected resource is addressed by a logical reference — secure://payments/production/stripe — backed by an opaque identifier (r_82f1...) so that human naming never becomes the security boundary. A resource holds credential versions: v17 → revoked, v18 → active. Applications keep requesting the stable reference, so rotation becomes a data-plane operation instead of a redeploy.
A capability is the authorization object: a signed statement that principal P may perform operation O on resource R for audience A until time T, with a nonce to prevent replay. Crucially, sign, read-secret, and export are different operations, and a workload is granted the narrowest one that works.
Policy stays boring on purpose
The initial policy language is deliberately small:
identity: spiffe://acme.example/prod/payments/api
allow:
- resource: payments/stripe
operations:
- sign
Default is deny. Later versions can add environment, branch, region, time, and deployment context — but the policy language must never become a second programming language, and every denial should be explainable: who was denied, what, why, and what would have been required instead.
Cryptography without invention
Two standard constructions carry the design:
- Authenticated encryption for stored resources. Confidentiality alone is not enough — an attacker must not be able to flip
resource = productiontoresource = developmentin a ciphertext header without detection. AEAD authenticates that metadata alongside the content. - Envelope encryption for key authority. A data-encryption key protects the credential; a key-encryption key (in KMS/HSM/OpenBao Transit) protects the data key. The system integrates with existing key infrastructure rather than shipping a proprietary KMS.
The one crypto rule worth stating plainly: SHA-256 + AES + SHA-256 + Base64 is not a design. The design is AEAD, envelope encryption, versioned keys, and nothing custom.
Bootstrap
The hardest question in any identity system is how a workload gets its first trusted identity. The options are known: SPIFFE bootstrap, cloud workload identity, GitHub OIDC, one-time enrollment, TPM-backed identity. The prototype will use the simplest mechanism that still demonstrates the boundary (one-time enrollment); production deployments should prefer established workload identity wherever it exists.
VI. Runtime Flows
The compatibility path
Some SDKs will only accept a raw secret, and pretending otherwise breaks the migration story:
app → secure.secret(resource) → agent → identity check
→ policy (ALLOW) → capability → decrypt/resolve → credential in app memory
This path exists, it is labeled compatibility, and its exposure is the documented reason the stronger path matters.
The preferred path: brokered signing
app → secure.sign(resource, payload) → agent
→ capability verified → broker
→ credential used inside broker → signature returned to app
The application receives a signature — never the key. For an HMAC secret this is the cleanest possible proof of concept, because the security property is trivial to test: the key material simply never crosses the IPC boundary.
Control plane off the hot path
The naive architecture authorizes every operation through the control plane and dies whenever it is unavailable. The proposed one does a single authorization at startup or renewal, receives a time-limited capability, and enforces it locally until expiry — trading a little latency and network dependency at the edge for dramatically less control-plane load and availability risk. Near expiry the agent renews; if renewal fails, existing leases run to their natural end, and new operations are denied rather than silently allowed.
Revocation is not rotation
Revoking a capability ("this workload may no longer use the resource") and revoking the external credential ("the provider no longer accepts the key") are different operations with different consequences, and the UI and docs should never blur them. The same discipline applies to rotation: where the provider has an automated rotation API, the system can drive it; where it does not, rotation is a guided manual process with overlap for zero-downtime migration. The design promises no universal automatic rotation, because that promise would be false.
VII. Deployment Shapes
The same core protocol is meant to serve very different environments, with only the enforcement topology changing:
- Local:
secure init --local+ CLI + SDK against a local encrypted store. No cloud service required — important for students, side projects, and offline work. - VPS: application plus an optional agent; the control plane handles identity, policy, and audit, not every API call.
- Docker: the image contains the app, the SDK/runtime, and encrypted references — and, by design, no plaintext production credentials. The same image can move across environments:
ENTRYPOINT ["secure", "run", "--"]. - Kubernetes: workload identity via SPIFFE/SPIRE or Kubernetes-native mechanisms, agent as a sidecar. The core protocol stays Kubernetes-independent.
- CI/CD: GitHub OIDC gives the workflow a short-lived identity, and policy keys off it — main branch deploys to production, pull requests get staging, forks get denied. Untrusted pull-request execution is an important test case because it separates "the repo is trusted" from "this execution is trusted."
This is really one migration path, not five products: a small project starts with encrypted references, and grows into identity, capabilities, a local broker, and cloud scale only as it needs them.
VIII. Developer Workflow
The workflow is designed to feel like fixing the problem, not like adopting a platform:
secure init
secure scan # find plaintext credentials + historical exposure
secure protect # replace values with secure:// references
git commit && git push
secure run -- npm start
secure scan is the on-ramp: it examines source, env files, manifests, CI files, and git history, detecting credentials by pattern, entropy, and field name, and it reports confidence rather than screaming at every random string — 98% AWS credential — CRITICAL vs 12% random identifier — LOW. The git-history mode is where scanners usually stop and this one should not: a credential removed from the current tree but present in history is still compromised, and the output should say revoke it, not commit the fix.
Two less obvious pieces matter for adoption:
- Policy simulation (
secure policy test) — ask "what would happen if this workload requested this resource" before deploying a policy change. It prevents the worst class of policy bugs (the ones that deny production in an outage) and doubles as documentation. - Explainable denials — every refusal returns identity, resource, operation, and reason. Opaque "access denied" errors are how debugging time disappears and how security teams learn to hate their own tooling.
The web console, when one exists, should manage organizations, resources, policies, and audit — and should not be the place where production credentials are pasted. Encryption happens locally, in the CLI or in the browser, and only ciphertext travels to the server.
IX. Security Analysis
Walking the main scenarios shows where the architecture holds and where it honestly does not:
- Repository theft. The attacker gets ciphertext and
secure://references but no workload identity. Capability issuance fails at the identity check. Encryption carries this scenario — which is exactly what encryption is for. - Staging asks for production. Identity is bound to the workload and environment; policy denies cross-environment requests. This is the case where static shared credentials fail and workload identity earns its complexity.
- Forked pull request. The workflow runs with a fork's OIDC context, and policy says untrusted PRs touch nothing. What matters here is that authorization keys off execution context, not repository membership.
- Capability replay. A stolen capability must fail against every axis it can be checked on — wrong audience, wrong principal, wrong resource, wrong operation, or an expiry that has passed. Nonces and short lifetimes make replay a narrow, fast-closing window.
- Modified ciphertext. AEAD authentication rejects tampering with the resource, environment, or version metadata before decryption is even attempted.
- Compromised application. In compatibility mode the attacker recovers the credential — a stated limitation. In broker mode they recover the ability to make authorized requests but not the key material. The difference between those two outcomes is the entire point of the architecture.
- Compromised agent. The agent is a critical boundary and should be built accordingly: no global enumeration, no unrestricted export, no access to resources its own policy does not authorize. A tiny, auditable data plane beats a feature-rich one.
- Compromised control plane. Compromise of metadata must not imply recovery of plaintext. Separating metadata, ciphertext, and key authority — with KMS/HSM holding the keys — keeps a control-plane breach from becoming a credential breach.
- Full host compromise. The honest answer is that local guarantees collapse, and the correct response is architectural: move the sensitive operation into a stronger trust domain.
X. Evaluation Plan
This section is written in the future tense on purpose. The prototype has not been built, and no numbers in this paper are measured. What exists is a definition of what would count as evidence, so the eventual evaluation cannot be retrofitted to flatter the results.
The evaluation is planned across five dimensions:
- Security. Unauthorized-access attempts, capability replay, cross-environment access, repository-only recovery, and credential disclosure in brokered operations — each as a repeatable test with a pass/fail outcome.
- Performance. p50/p95/p99 latency and throughput across five baselines: direct operation, library-only security, local agent, remote authorization with local operation, and brokered signing. The interesting number is not "is the broker slow" but "how much does each security increment cost."
- Availability. Failure injection against the control plane, identity issuer, database, KMS, agent restart, network partition, expired lease, and clock skew — recording expected vs. observed behavior, recovery time, and the security consequence of each degraded mode.
- Scalability. Capability-request load from 10 to 10,000 workloads, watching control-plane and data-plane behavior separately.
- Usability. Setup time, configuration steps, files modified, and time to migrate a repository and a local→production path. A system that is theoretically safer but costs forty manual steps will fail in adoption, and that failure is a research finding, not a marketing problem.
The PoC scope stays intentionally narrow: a Go core, CLI, Node SDK, encrypted resource format, one identity method, the minimal policy engine, capability issuance, a local agent, the HMAC broker, audit logging, Docker packaging, and the git scanner. Explicitly excluded from the first cut: twenty SDKs, a full Kubernetes operator, multi-region HA, a universal provider proxy, and dynamic database credentials.
Ten acceptance criteria define "done" for the prototype, all demonstration-grade: a credential protected before commit; repository theft yielding nothing; an authorized workload obtaining a valid capability; an unauthorized one denied; expiry enforced; tampered capabilities and ciphertext rejected; brokered HMAC never exposing the key; audit events free of credential material; a control-plane outage not killing a valid lease; and the whole thing running in both local and Docker form.
XI. Limitations & Future Work
The limitations deserve the same honesty as the non-goals: authorized-process compromise in compatibility mode, host compromise, bootstrap complexity, policy errors, control-plane outage, SDK supply chain, provider-imposed limits on granularity, and the reality that rotation can only be as automated as the provider allows. Each is classified as solved, mitigated, out of scope, or future work — never silently ignored.
The directions that excite me most are the ones that push the "don't give the credential away" idea further: confidential computing and remote attestation for high-value keys (proving not just who the workload is but what software it runs), hardware-backed identity via TPM, and treating AI agents as workloads — an agent with a narrowly scoped capability to call a tool is a much better security model than an agent holding a bag of API keys. On the product side, automated least-privilege inference — watching what a workload actually does and recommending stripe/webhook/sign instead of stripe/* — would close the loop between the architecture and the messy reality of existing code.
XII. Conclusion
The problem this project targets is not "insecure API key storage." It is the deeper architectural habit of credential ownership — the assumption that an application which needs to perform an operation must possess the credential that enables it.
The proposed layer answers that by dividing the problem: encryption protects credentials at rest; workload identity establishes who is asking; policy decides what that workload may do; capabilities bound that permission in time and scope; and the broker makes credentialless execution possible where it matters most. Each piece exists in production today, in some form — SOPS, SPIFFE, OpenBao, Infisical all prove it. The contribution proposed here is the connective tissue: one capability-oriented model that carries a workload from an encrypted reference in git to a narrowly authorized, short-lived, possibly credentialless operation at runtime.
The strongest protection will never be a vault or an agent; it will be the discipline of asking why the application holds that key at all — and the availability of a safe answer that is not "because that's how SDKs work."
References
- OWASP Foundation. Secrets Management Cheat Sheet. Guidance on storage, least privilege, lifecycle, rotation, expiration, auditing, and CI/CD secret handling.
- NIST. SP 800-207: Zero Trust Architecture. August 2020.
- NIST. SP 800-207A: A Zero Trust Architecture Model for Access Control in Cloud-Native Applications in Multi-Cloud Environments. September 2023.
- SPIFFE Project. SPIFFE Standard, Workload API, and Workload Endpoint. Workload identity and local identity retrieval.
- Mozilla / CNCF. SOPS — Secrets OPerationS. Encrypted-file tooling for YAML, JSON, ENV, INI, and binary formats with KMS/age/PGP integrations.
- AGWA. git-crypt: Transparent File Encryption in Git.
- OpenBao Project. Transit Secrets Engine. Cryptographic operations without storing application data.
- GitHub. About security hardening with OpenID Connect. OIDC claims for workflow identity in GitHub Actions.
- Infisical. Agent and credential brokering documentation.
- Mordor Intelligence. Secrets Management Solutions Market Size & Share (2025–2030). Estimates USD 4.22B in 2025 growing to USD 8.05B by 2030.
Appendix: PoC Scope
In the first prototype: Go core, CLI, Node SDK, encrypted resource format, one workload identity method, minimal policy engine, capability issuance, local agent, HMAC broker, audit logging, Docker packaging, git scanner.
Explicitly deferred: multiple SDKs, Kubernetes operator, multi-region HA, universal provider proxy, dynamic database credentials, HSM orchestration.
Recommended demo: clone a project with plaintext credentials, secure scan, secure protect, commit, secure run — then show repository theft yielding nothing, a staging identity denied production, a production identity obtaining a signature, and the signing key never leaving the broker.
Thesis, stated once: an application should be able to use a credential without permanently owning the credential — and when the operation can be safely delegated, it should be.