What it can reach,
and what it cannot.
Written for the person who has to approve this tool. Every claim below was checked against the source on 2026-09-20. Where something could not be checked, the page says “not yet documented” instead of guessing.
- Hosts of ours
- None. No licence check, no update check, no telemetry, no crash reports.
- Credentials beside it
- Your Jira token, a GitHub token and your Anthropic key; a TypeSafe key only if you choose TypeSafe triage.
- Where your code goes
- Into tickets on your Jira site, redacted and capped at 50 lines and 4 KB; to api.anthropic.com only when your key is set; to api.typesafe.ai only if you choose it; and to your git remote as one branch per fix.
- Not yet documented
- What the programs
scanstarts load from a hostile repository; the scanners' own connections, host by host; GitHub Enterprise Server; scoped Atlassian tokens.
Your repositoryread in place; scan writes nothing to it
jiraagentson a laptop, in CI or in a container, with your tokens
127.0.0.1:4330the dashboard, on loopback
Your Jira sitetickets, with code capped at 50 lines and 4 KB
api.github.com and your git remotepull request state; one draft pull request per fix
api.anthropic.comonly with your key; it receives source code
Public sourcesthe semgrep.dev ruleset, fetched at initscanner databases: not yet documented
Jadexnothingno request, no token, no telemetry
It sits next to
three credentials, four if you choose TypeSafe.
Be blunt about it, because the rest of the page only makes sense in this light. A compromise of this package would not be an npm incident. It would be a credential compromise for every engineer who installed it.
Your Jira identity
An unscoped Atlassian API token is full impersonation of the person who made it: every project that person can see, not only the one you file into.
Your GitHub identity
Typically the repo scope, across every repository that person can reach. solve uses it to push one branch and open one draft pull request.
Your model spend
Spend on your account, and the contents of every prompt the tool builds, which include your source code.
Only if you choose TypeSafe triage
Spend on your TypeSafe account, and the redacted code and scanner text of every finding triage assesses. Off by default.
Where it connects.
The last row is us, and it is empty.
The tool's own HTTP requests go through one module, and the Anthropic SDK is imported in four files. Those rows are complete, and that is what makes them possible to write. The programs it starts make connections of their own, and those rows say “not yet documented” wherever nobody has traced them host by host. Each row says which host, when, what is sent, and who chose it.
Your Jira site
- Host
- Your credentials go to exactly the URL in
JIRA_BASE_URL, which must be https. Nothing is derived or guessed. They are never sent tojira.baseUrlfrom the config file: that value is used only for the unauthenticated time request below. - When
doctor,plan,ingest,apply,baseline,revertandsolvemake authenticated requests.ingest --dry-runmakes one: a read-only search of this repository's tickets, for the near-duplicate check, skipped when every finding is already known locally. It files nothing (added and checked 2026-09-30).status,prsandconfirmmake none, but they read the three Jira variables and refuse to start without them. Before anything authenticated, each of these asks the site for the time with no credentials, so timestamps come from Jira and not from your laptop clock.scanasks the time too when a base URL is configured, and needs no credential.- Sent
- Your Jira email and API token as HTTP basic auth, label searches, and the tickets themselves: rule, path, line, and the matched code after secret redaction, capped at 50 lines and 4 KB.
api.github.com
- Host
- The GitHub REST API. The pull request status reader honours
GITHUB_API_URL. GitHub Enterprise Server has not been exercised: not yet documented. - When
solvetakes a claim on a ref namedrefs/jiraagents/claim/<KEY>before it works, and first asksapi.github.comfor the time with no credentials, so the lease is stamped by the clock of the system the fence lives in.plan,prsandstatusread the state of the pull requests the tool opened.- Sent
- A token from
GH_TOKEN,GITHUB_TOKENorgh auth token, as a bearer header. The time request carries no token.
Your git remote, through git and gh
- Host
- Whatever
originpoints at in the repository you run in. - When
solveonly, and only after the ten gates this release runs have passed. The other seven say unverified, and that is reported on the pull request, never counted as a pass. The CLI runsgit pushfor the solver branch andgh pr create --draft. The agent itself cannot push.- Sent
- One branch and one draft pull request, under whatever identity your git and gh are logged in as.
api.anthropic.com
- Host
- The Anthropic API, or the address in
ANTHROPIC_BASE_URLif you set one. Contacted only whenANTHROPIC_API_KEYis in the environment. - When
- The review lenses during
scan, which are ON by default when the key is present. Alsoplan --triage,ingestof a prose report, andsolve. - Sent
- Your source code. A lens reads whole files from the slice it was handed. Turn the lenses off with
scan --no-lenses, or for good withlenses.enabled: []in the config. With no key, none of this runs and the run says so.
api.typesafe.ai
- Host
- TypeSafe AI, a third party, for its Jev classifier. Contacted only when
triage.provideristypesafeandTYPESAFE_API_KEYis set. The default provider is Anthropic, and then nothing goes here. - When
- Whenever triage runs:
plan --triage, and withtriage.enabled: truealsoplan,applywithout--from, and the plans the dashboard draws. Neverscan. One request per finding. Before the first one, every run prints where the findings are going and whether the provider, the model and the key came from you or from the repository being audited; on the dashboard that line goes to the server's log.JIRAAGENTS_TRIAGE_PROVIDER=anthropicin your shell overrules the repository. Added and checked against the source on 2026-09-30. - Sent
- Code from your repository. For each finding: the matched code after secret redaction, its path and lines, the rule, the CWE, the severity, the names of the tools that reported it, its reachability label, and the scanner's own title and message. Your TypeSafe key as a bearer header. Nothing else about your machine or your credentials.
semgrep.dev
- Host
https://semgrep.dev/c/p/ci, the public rules registry.- When
initanddoctor --fix, to download the ruleset once and pin its hash. Not duringscan: scans read the cached file and run semgrep with--metrics=off.- Sent
- An anonymous GET. No login, no token, nothing about your repository.
The scanners and package managers it starts
- Host
- Not ours to fix, and not yet documented host by host.
uvxfetches the pinned semgrep from the Python package index on first use.osv-scannerqueries the OSV vulnerability database.trivydownloads its own database.npm auditorpnpm auditasks the npm registry your own npm configuration names. On a machine with Homebrew,install-tools --yesrunsbrew installfor the toolsdoctorreported missing, which reaches Homebrew and wherever its formulae download from, and it warms theuvxcache with the pinned semgrep. Without--yesit prints every command and runs none. Where there is no Homebrew it prints the install commands for you to run yourself, and never pipes a downloaded script into a shell. - When
scan, for semgrep and osv-scanner. trivy runs only with--deep. The audit call runs only when there are dependency findings, to look up an upgrade path, andscanners.remediation.enabled: falseturns it off.install-toolsruns only when you type it.- Sent
- Whatever each of those tools sends. For a vulnerability lookup that is package names and versions from your lockfile.
Strix: your target, its model provider, a container registry
- Host
- Three kinds, and the tool fixes none of them. The URL in
scanners.strix.app_url, which Strix attacks. The model provider Strix is configured for, through its ownSTRIX_LLMandLLM_API_KEYvariables, which jiraagents neither reads nor sets, and does not load from your.env. And the registry Strix pulls its sandbox image from on first use, several gigabytes. Which hosts those last two are is not yet documented. - When
scan --deep, and only withscanners.strix.enabled: true, which is off by default. It also needs a target URL and a running Docker daemon, and says which is missing instead of skipping quietly.- Sent
- Attack traffic to the URL you named. Strix is an agentic penetration tester, not a static analyser: it sends real exploit attempts, so point it at staging you are authorised to test and never at production. It spends your model budget up to
scanners.strix.max_budget_usd. What Strix sends to its model provider is not yet documented.
127.0.0.1, the dashboard
- Host
- A local HTTP server, bound to
127.0.0.1unless you say otherwise. Its pages load nothing from the internet. - When
jiraagents dashboard.- Sent
- Nothing leaves the machine. Bound to a reachable address it refuses to start without
JIRAAGENTS_SERVER_TOKEN, and it refuses every job that writes, because a shared token cannot say which person made the change.
Any host operated by us
- Host
- None. The command line tool contains no request to this site or to anything else we run.
- When
- Never. Not for licensing, not for updates, not for telemetry, not for crash reports. There is no licence check, no update check and no analytics library in the package.
- Sent
- Nothing. This site's address does not appear in the code.
What scan starts,
and what solve may touch.
scan runs no test, no build and no install
scan never runs your test suite, your build, your install or any script your repository defines. It starts three static analysers: semgrep against a pinned local ruleset file, osv-scanner, and with --deep trivy. Each reports on standard output and none is given an output path, so nothing is written into the repository being audited. Test coverage arrives through ingest, from a report you produced yourself, for exactly this reason.
The fourth scanner is not static: Strix attacks a running target
Strix is the one scanner that is dynamic. With scan --deep and scanners.strix.enabled: true, which is off by default, the tool starts strix against the URL in scanners.strix.app_url. Strix runs an agent swarm inside a Docker sandbox, sends exploit attempts to that URL, for an hour or more on a deep run, and spends a model budget you cap with scanners.strix.max_budget_usd. The tool starts it in its own cache directory, not in your repository, and reads the run files from there. A run that stops at the budget is reported as partial coverage, never as a clean result.
Not yet documented: what those programs load from a hostile repository
The analysers, and git, npm and pnpm, are third-party programs started inside your repository's directory, and some of them read configuration files they find there. We have not yet gone through them one by one and written down what each will load from a repository that is hostile rather than merely buggy. Every program the tool starts also inherits the environment it was started in, including any token in it. Until that is documented, do not treat scan as safe to point at a repository you do not trust. Run it in a container or a throwaway machine with no credentials in the environment, as you would before opening that repository in any other developer tool.
The solver has three tools, and none of them is a shell
The agent behind solve can read a file, write a file, and say it is done. It has no command execution and no network access of its own. It works in a disposable git worktree with realpath containment, so a symlink cannot lead it outside. It may not write CI configuration, .github, package.json or .npmrc, except in a small set of fixed diff shapes that are re-derived from git at the gate. It never writes a lockfile: the CLI regenerates that with the real package manager and --ignore-scripts. jiraagents doctor --print-policy solver prints the whole policy.
solve does not run your test suite in this release, and says so
The gate that would compare your tests before and after a change reports unverified, in words, rather than a pass. A solver pull request is a draft for that reason among others. The agent takes no irreversible action; the CLI pushes, after the ten of the seventeen gates this release runs, and never opens a pull request that is ready to merge.
By default it is you.
It does not have to be.
Out of the box the tool inherits your own authority in Jira and in GitHub, and every audit log
names you rather than the tool. doctor names the account it authenticated as, in
its jira-identity and gh-auth rows, and adds a caveat to
gh-auth when the token carries the workflow scope. It does not warn
that you are running as a person: that check does not exist yet.
A service account, scoped to one project
Instead of a personal API token, use an Atlassian service account whose permissions stop at the one project you file into. It needs to browse, create, edit, comment on and transition issues there (with jira.sandboxSprint set, also schedule issues, which is the permission Jira asks for to put an issue in a sprint), and nothing at site level: the tool never creates a project, a field, a workflow or a screen.
Atlassian serves scoped tokens through api.atlassian.com/ex/jira/<cloudId> rather than your site URL. We have not exercised that route end to end: not yet documented.
A GitHub App or a machine user
Give it contents: write and pull_requests: write on an allowlist of repositories, and no Actions or workflow permission. The cost: GitHub refuses a push that changes a workflow file from an identity without that permission, so the one fix shape that edits a workflow, pinning an action to a commit SHA, will not push under it.
The claim fence needs contents: write on refs/jiraagents/claim/*. The tool has only ever been run as one personal identity. A fine-grained token and an organisation that enforces SSO have not been tried: not yet documented.
scan, explain and both exports need neither credential. A reviewer can evaluate what the
tool finds with no token on the machine at all.
No install scripts.
Readable JavaScript.
npm install -g @jadex-consulting/jiraagents --ignore-scripts
The package has no preinstall, install, postinstall or prepare script, and a test fails the build if one appears. The flag therefore costs you nothing here, and it protects you from every transitive dependency that does have one.
npm view @jadex-consulting/jiraagents@<version> dist.integrity
Compare the hash with the integrity field your lockfile recorded for the same version. npm audit signatures checks the registry's own signature on what you installed. There is no build provenance attestation yet: npm only attests a build it can link to a public commit, and the source repository is private.
What you installed is readable.
The tarball ships the compiled dist directory only: plain JavaScript as the TypeScript compiler emitted it, not minified, not bundled, comments intact. The licence inside the package grants no right to use or read it by itself: that right comes from the written agreement under which a company uses jiraagents. If your review needs that permission in writing before an agreement exists, ask for it at the address under “Email us”, below. Either way the software is proprietary: nothing here is a right to modify or redistribute it.
What it does
with secrets.
Tokens are wrapped before they travel
Credentials are held in a type whose string, JSON and inspector forms all print a redaction marker, so one cannot leak through a log line, an error or a template.
Nothing secret enters the audited repo
State lives outside the working tree, under your own state directory. doctor fails hard if a .env file is tracked by git.
Known limitations,
stated rather than buried.
The local audit journal is not tamper-evident
It is an append-only file on the machine of the person you would be investigating, and a process that can write a hash chain can rewrite it. The records that resist an adversary are external: Jira's audit log, GitHub's organisation audit log, and the audit property the tool writes on every issue it touches.
The semgrep ruleset pin is trust on first use
The ruleset is served anonymously, unsigned and unversioned. Whoever runs init first establishes the hash, and a hostile ruleset served at that moment would be pinned faithfully. It is pinned anyway, because an unpinned ruleset silently changes what is found.
Multi-operator safety exists for solve and not for apply
solve takes a claim before it works. apply takes none, so two people running apply at the same moment are not fenced from each other. Run apply from one place, such as a single CI job. Nobody has yet raced two real machines for one ticket, so the claim fence itself is unmeasured under contention.
Email us.
Do not open a public issue.
Write to the address below, with [jiraagents security] in the subject: each route fills it in for you. Include the version (jiraagents --version) and what you observed. If a credential may have been exposed, say so in the first line: rotation comes before analysis.
dhillon.vo@jadexconsulting.com
Each opens a new message with the subject “[jiraagents security]”. If none of them is how you read mail, copy the address: one click selects all of it.
You will get an acknowledgement within two working days. Please do not send a working exploit for somebody else's product: a finding in an upstream dependency belongs with that project's maintainers.