I joined Temporal a year ago to grow the Application Security program and found myself in a familiar situation, one that I’m sure echoes the experience of many security engineers: no single tool was meeting our requirements. Scanning was slow and increasingly fragmented across a variety of tools just to get coverage. We had a slew of “critical” vulnerabilities to triage that turned out to be false positives, and even a few false negatives. All the while, we were battling a growing number of supply chain security concerns, adding cooldowns where possible, and trying to balance defense in depth with developer velocity.
It’s simple as a concept: manage vulnerabilities. In practice, it’s a bit of a nightmare. So I started building what I’d been wishing I had.
Meet the new Deputy in town.
Deputy is an open-source, CLI-first security toolchain for inventorying, scanning, triaging, and controlling dependencies across repositories, container images, VM disk images, SBOMs, and other targets. It gives security teams and developers a shared, customizable policy layer they can use locally, in CI, and at download time.
I used Claude Code and Codex to help build Deputy. In turn, Deputy lets us put deterministic supply chain analysis, policy, and execution guardrails around AI-assisted work. It doesn’t eliminate the risks of AI-generated code or compromised dependencies, but it gives both humans and agents better guardrails for understanding and controlling them.
The false positive machine#
You pick a tool, and it tells you there are thousands of high and critical alerts across your estate. At least the dashboard is kind of pretty, once it loads. You roll up your sleeves and go sifting through the sea of red, only to find that nearly all the alerts are false positives or, because of circumstances the tool can’t see, aren’t exploitable.
If you’re lucky, reachability analysis helps. Tools like govulncheck go a long way, but they aren’t perfect. Just because a vulnerability is reachable doesn’t mean it’s exploitable. It’s nuanced, and context matters. Signals like CISA’s Known Exploited Vulnerabilities (KEV) Catalog, the Exploit Prediction Scoring System (EPSS), and other dimensions can help, but understanding a vulnerability within the context of your estate remains tricky. There’s a subtle art to it, one that you refine over time.
Tell me if you find yourself nodding along: to fix issues, you configure automated vulnerability remediation, only to have the pull requests go ignored. Sometimes accidentally. It’s just too noisy. So you tune the configuration again, but it’s not quite intuitive. You set up pull request scanning to stop new issues, but you need the right feedback for a repository with multiple contributing teams, ambiguous ownership, and a CODEOWNERS file where everyone owns everything. The documented SLAs start to slip. You end up in an uphill battle against a false positive machine working against you.
The reality is that there’s no silver bullet for any of it. It takes constant work, dedication, a shifting strategy, and resources focused on finding the right signal. Finding that signal, then controlling it within your organization, becomes the art.
One inventory, many targets#
Deputy helps you inventory, scan, diff, triage, and fix packages across a variety of targets and ecosystems. It can also run package manager commands with sandboxing controls, proxy package downloads, and apply customizable policies.
Point it at a repository, directory, container image, VM disk image, SBOM, or single package by Package URL (PURL), and Deputy reconciles what it finds into a single inventory you can inspect. Deputy is a CLI-first project with a plugin system, so it’s extensible across a variety of use cases and easy to integrate with the systems you already use. Its MCP server, for example, exposes Deputy’s vulnerability analysis and remediation planning capabilities to coding agents and other MCP-compatible tools.
To build that inventory for a target such as a GitHub repository, Deputy uses a variety of built-in package extractors on top of Google’s OSV-SCALIBR library, along with custom extractors we hope to contribute upstream. These produce the foundational pieces, including a package name, version, and other relevant metadata. Deputy can then augment that data with license metadata, known vulnerability data, advisory source provenance, publication metadata, and optional exploitability enrichment such as KEV and EPSS to build a richer picture of each dependency.
Policies that travel with the work#
Many factors shape what you might trust, what you want to prevent, and what requires explicit acknowledgment or an exception. Deputy exposes its package and vulnerability data through a policy system, so you can make precise decisions about how to handle a given situation.
Policies are written in YAML using CEL, the Common Expression Language. Policy bundles are portable across local development, CI, and Deputy’s artifact proxy. Rules remain explicitly scoped to the entrypoints whose inputs they use, so one bundle can contain both scan-time and download-time controls.
Here are three examples.
Exploit signal gate#
Run the scan with --enrich to deny vulnerabilities already in CISA’s Known Exploited Vulnerabilities catalog or with an EPSS score of at least 0.1. Without enrichment data, the optional values default to false and zero, so the rule evaluates cleanly without matching.
policies:
- name: exploit-signal-gate
entrypoints: ["scan_vulnerability"]
vars:
epss_threshold: 0.1
rules:
- action: deny
when: |
vulnerability.?in_kev.orValue(false) ||
vulnerability.?epss.orValue(0.0) >= epss_threshold
reason: vulnerability is in CISA KEV or has an EPSS score of at least 0.1
Vulnerability SLA#
This is the kind of rule that’s painful without a real expression language. Don’t fail the build on a brand-new high or critical advisory. Fail only when it has been public for more than two weeks and the advisory lists a fixed version. New issues get a grace period while older issues with a listed fix don’t.
policies:
- name: high-critical-fix-sla
entrypoints: ["scan_report"]
vars:
grace_period: duration("336h") # 14 days
rules:
- action: deny
when: |
vulnerabilities.exists(vuln,
vuln.?advisory.severity.level.orValue(severity.unspecified) >= severity.high &&
vuln.?advisory.fixed_versions.orValue([]).size() > 0 &&
vuln.?advisory.published.hasValue() &&
now() - timestamp(vuln.advisory.published) > grace_period)
reason: high or critical advisory with a listed fix exceeded the 14-day SLA
Warn on lookalike npm packages before download#
Policies can also run directly in package-manager workflows. This rule warns when an npm package download is one edit away from a protected package name. Exact package names and missing metadata do not match, and teams can promote the warning to a denial after tuning the protected list.
policies:
- name: review-lookalike-packages
entrypoints: ["npm_artifact_request"]
vars:
protected_packages: ["react", "lodash", "express"]
requested_package: 'request.?package.orValue("").lowerAscii()'
rules:
- action: warn
when: |
request.operation == "download" &&
requested_package != "" &&
!protected_packages.exists(name, requested_package == name) &&
protected_packages.exists(name,
levenshteinWithin(requested_package, name, 1))
reason: requested package is one edit away from a protected package
remediation: verify the intended package name
You can express other vulnerability and dependency guardrails the same way, including different thresholds for direct and transitive dependencies or whatever fits your organization. Deputy helps you express your intent and enforce it deterministically, which makes it a good fit for agent, developer, and CI/CD workflows alike.
The point is to put up guardrails developers can actually live with instead of another gate that gets ignored or worked around.
From findings to action#
There are plenty of tools to warn you about issues. Deputy also helps you triage and fix them. Use deputy triage to understand and prioritize findings. Run deputy fix to generate an explicit remediation plan first, so you can review it, export it, or apply it.
If you want an agent to do the legwork, that’s built in too. Deputy can catch things early during an agent session or in a pull request, as well as out of band when you’re triaging something quickly or responding to an incident.
Two features push enforcement even earlier than scanning can.
deputy exec runs package manager commands and build scripts with sandboxing controls. Depending on the runtime and configuration, workspace isolation, secret-file masking, network allowlists, and resource limits can help shrink the blast radius of a command such as npm install.
deputy proxy enforces policy at download time across Go, npm, PyPI, RubyGems, and OCI container registries. It uses the same policy bundle to block risky package or container image downloads. For teams running a central proxy, Deputy supports JWT authentication through OIDC/JWKS.
None of this makes risk disappear. A bad package can still poison what you ship. Deputy is one layer in a broader defense-in-depth strategy, not the whole thing.
Deputy’s core workflows don’t require an agent. When you use one, keep analysis read-only and review the remediation plan and resulting diff before merging agent-made changes.
What Deputy is, and what it isn’t#
Deputy is deliberately scoped. It doesn’t currently perform application-level vulnerable call-path analysis, nor is it an Application Security Posture Management platform with yet another dashboard to log into. It gives you better signal and a deterministic way to act on it, from the command line or an agent session, inside the work you’re already doing.
Deputy is also early. It’s been in development for about a year and still has some rough edges. It isn’t perfect, not yet. But we’re proud of what we’ve built and where we’re going, and we want to take you along for the ride. It’s free to use and extensible, and we’re excited to make it better with you.
The project is open source under the Apache 2.0 license and lives at github.com/temporalio/deputy. It was built by Temporal’s Security team to meet Temporal’s needs first, and anyone can use, extend, and contribute to it.
If you’re concerned about the flood of malware and supply chain attacks, if you’re picky about the dependencies you bring in, and if you want to wrangle, understand, isolate, and control them with precision, we’d love to hear from you.
To take it for a spin:
go install github.com/temporalio/deputy@latest
Check out the repository for the code, documentation, and everything else you need to get started with Deputy. We’ll have more to share soon.