Repository navigation
v0.1.0
First public release.
Changed
JUNCTIO_DATA_DIRdefaults to./datainstead of/data, so a source-tree run no longer tries to write to the filesystem root. The image still sets it to/data, which is where the named volume is mounted, so a container deployment is unaffected.
Security
POST /v1/session/setupnow requiresJUNCTIO_ADMIN_TOKENwhen one is configured. A headless deployment that relied on the token no longer leaves the first-run password endpoint open to anyone who can reach it.- OAuth tokens issued by the built-in authorization server are bound to a resource.
resourceis now required at/oauth/authorizeper RFC 8707, and the verifier rejects a token whose audience does not match the endpoint. A token minted for one endpoint no longer works on another, nor on the management server. - Management MCP tools validate every identifier as a UUID, so a tool argument can no longer smuggle a path segment into the REST router and reach an operation the management server does not expose, such as lifting a quarantine.
- The origin check no longer falls back to echoing the
Hostheader, which closes a DNS rebinding path to every endpoint withauthMode: "none". WithJUNCTIO_BASE_URLunset only loopback origins matching the host are accepted. - Every response carries
Content-Security-Policy,X-Frame-Options,X-Content-Type-Options,Referrer-PolicyandPermissions-Policy; API responses are markedno-store. - The session cookie is marked
Securebehind a TLS-terminating proxy whenJUNCTIO_TRUST_PROXYis on, not only whenJUNCTIO_BASE_URLis https. /oauth/authorizeand/oauth/tokenare rate limited. The login limiter dropped its global bucket, which an attacker could use to lock out the real operator.- With
JUNCTIO_TRUST_PROXYon, the client address is taken from the right-mostx-forwarded-forentry, the one the fronting proxy appends, instead of the client-supplied left-most one. - Refresh token rotation keeps the original grant time, so the 30-day lifetime is now absolute rather than sliding indefinitely.
- Agents can no longer change
runtimePathorauditIntervalHoursthrough the management server, and the settings handler enforces the agent schema rather than trusting the tool definition. - Encryption keys are derived with scrypt from
JUNCTIO_SECRETand a random per-database salt instead of a single unsalted SHA-256. The minimum secret length is now 32 characters. - Links coming from the public registry and from advisory data are rendered only when they are
http:orhttps:, closing ajavascript:injection into the admin UI. - The
enabledflag can no longer be flipped back on for a server the audit disabled until a fresh audit comes back clean, and editing a server in the UI no longer silently re-enables it.
Added
- A launch gate: with the audit enabled, a server whose packages have never been checked, or whose last check failed, refuses to start and queues an audit instead of launching unverified code. The gate covers the pool, warm start, crash restart and the test button.
- CVSS v3 vectors from OSV are scored instead of being discarded, so a PyPI advisory carrying only a vector no longer collapses to
unknown. An unknown severity now ranks as high rather than moderate. - Biome for linting and formatting, wired into CI.
CONTRIBUTING.md,CODE_OF_CONDUCT.md, issue and pull request templates, and Dependabot.
Fixed
uvxanduvwork on a read-only root filesystem. The image setsUV_PYTHON_INSTALL_DIRandXDG_DATA_HOMEinside/cache, without which the PyPI audit engine and everyuvxserver failed in the published configuration.- A stop and an acquire in flight no longer overlap, which could leave a second process or container running behind the first.
- A server whose transport was closed, typically after a slow handshake, is replaced instead of being handed the same dead transport forever.
- The audit no longer resolves one set of packages while the server runs another: environment variables that redirect package resolution are dropped for audited runtimes.
- A failed lookup against osv.dev is no longer cached for a day as "no vulnerability", and a non-zero
bun auditexit or an error payload is treated as a failure. - The quarantine reason is refreshed when the findings change, and lifted quarantines are counted in the run summary.
- Renaming a server checks namespace prefix collisions, and a name containing the tool separator is rejected.
- PyPI and OCI installs from the registry pin the version the registry entry names.
- An unwritable
TMPDIRis reported as an error at startup instead of passing silently. - The admin UI handles an expired session, a failed request and a missing clipboard API instead of failing silently; the request log colours slow requests correctly; live server logs keep following past 500 lines.
Removed
- The plaintext
servers.envcolumn and its backfill. Server environments have been stored encrypted for several releases.
docker pull ghcr.io/k2so-dev/junctio:0.1.0