Skip to content

Security: EliorMachlev/JenkinsAsService

Security.md

Security Policy

Scope

This policy covers security issues in:

  • JenkinsAsService Windows Service (the .NET executable)
  • JenkinsAsService.Installer MSI package (WiX v5)
  • CI/CD workflows in this repository (GitHub Actions)
  • Documentation that could mislead users into insecure configurations

Out of scope:

  • Jenkins itself (report to Jenkins Security)
  • The Java runtime or JDK (report to your JDK vendor)
  • Third-party NuGet packages (report to the package maintainer; see Dependencies below)
  • Windows OS or DPAPI/Credential Manager subsystems (report to Microsoft)

Supported Versions

Only the latest release receives security fixes. Older versions are not patched — upgrade to the latest release to stay protected.

Version Supported
Latest release Yes
Older releases No

Reporting a Vulnerability

Do not open a public issue. Security vulnerabilities must be reported privately.

Preferred: GitHub Private Vulnerability Reporting

  1. Go to the Security Advisories tab
  2. Click "Report a vulnerability"
  3. Fill in the details and submit

GitHub will create a private advisory visible only to you and the maintainers.

Alternative: Email

If you prefer email, contact the maintainer directly. You can find contact information on the GitHub profile.

What to Include

A good report helps us fix the issue faster. Please include:

  • Description of the vulnerability and its potential impact
  • Affected component (service, installer, workflow, configuration)
  • Steps to reproduce or a proof-of-concept (if possible)
  • Environment — OS version, .NET version, JDK version, JenkinsAsService version
  • Suggested fix (optional, but welcome)

Response Timeline

Stage Target
Acknowledge receipt 3 business days
Initial assessment and severity 7 business days
Patch development 30 days for critical/high, 90 days for medium/low
Public disclosure Coordinated with reporter, after patch is released

Timelines are best-effort targets. This is a personal open-source project maintained by a single developer — not a commercial product with a dedicated security team.

Coordinated Disclosure

We follow responsible disclosure practices:

  • We will work with you to understand and reproduce the issue
  • We will keep you informed of progress toward a fix
  • We ask that you do not share details publicly until a patch is released
  • We aim to publish a fix and advisory simultaneously
  • You are welcome to self-disclose after 90 days if no fix has been released
  • We will never publish your identity or communications without your permission

If you would like to be credited in the advisory, let us know — we are happy to acknowledge reporters.

Security Architecture

JenkinsAsService handles sensitive data (Jenkins agent secrets) and runs as a privileged Windows Service. The following measures are in place:

Secret Protection

Secrets are never stored in plaintext by default (the MSI installer defaults to Dpapi). Five protection modes are available, strongest first:

Mode Mechanism Risk if host is compromised
Tpm TPM-bound, non-exportable RSA key (Platform Crypto Provider) Usable only on this machine's TPM, by a process that can access the key
Dpapi Machine-scoped DPAPI encryption Decryptable by any process on the same machine
CredentialManager Windows Credential Manager vault Accessible to processes running as the same user
EnvironmentVariable Machine-level environment variable Readable by any process on the machine
Unprotected Plaintext in appsettings.json Readable by anyone with file access

Dpapi additionally supports a User scope, which binds the ciphertext to the single identity that encrypted it — stronger than Machine, but it requires the secret to be written by the service account, so it is unavailable to virtual accounts and gMSA. appsettings.json itself is ACL-restricted to SYSTEM, Administrators and the service account.

At runtime the resolved secret is written to a separate ACL-restricted file and passed to the Java agent as -secret @<file>, so it never appears in the process table (where any local administrator could read it for the agent's whole lifetime). The file is rewritten on each restart and deleted on service stop.

Process and Filesystem Hardening

  • The Java agent child is launched with a deny-by-default environment — only a curated allow-list plus explicitly configured additions — so the service's own environment block cannot leak into untrusted pipeline scripts
  • Win32 process-mitigation policies are applied to the service process: no remote, low-integrity or non-System32 DLL loads, and legacy extension-point injection disabled
  • Binaries and runtime data are separated: the install folder stays read-only to the agent identity, while logs, the secret file, the jar cache and the build work directory live under %ProgramData%. A malicious pipeline therefore cannot overwrite the service binary and wait for a restart
  • The cached agent.jar lives in its own subfolder, isolated from the build workspace, and its SHA-256 is re-verified before reuse — trust-on-first-use local integrity, complementing controller certificate pinning for upstream authenticity
  • The service runs under a least-privilege virtual service account (NT SERVICE\Jenkins) by default
  • Uninstall leaves no secret behind, in any store: appsettings.json and the whole data folder are deleted, and the secret is removed from wherever the configured mode put it — the machine-scoped TPM key, the Credential Manager entry, or the machine environment variable. Only Unprotected and Dpapi keep the material in the config itself; the other modes store a pointer there, so deleting the file alone would leave a working agent credential on a host the product had supposedly been removed from. None of it is a tracked MSI file, so Windows Installer removes none of it on its own
    • Credential Manager entries are per-user. The uninstall runs as SYSTEM, so a credential written under another account (update-secret --impersonate) cannot be removed for you; the purge says so explicitly and prints the cmdkey /delete: command to run while logged on as that account

Secret Redaction

Agent secrets are scrubbed from all log output (file and Event Log) before being written. Every occurrence is replaced with ***** — and not only the literal value: the secret travels through a URL, a JVM argument and the controller's own error bodies before returning on the agent's stderr, so the URL-encoded, XML/HTML-escaped and Base64 forms are scrubbed too. A percent-encoded secret in a log file is just as disclosed as a plain one. Patterns are applied longest-first, so a shorter form cannot carve up a longer one and leave a recognisable fragment behind.

Network Security

  • TLS 1.2+ is enforced by default (.NET 10)
  • Jenkins controller URL requires an explicit port (a URL with no port is rejected); a non-HTTPS URL is allowed but warned at startup because the agent secret would be sent unencrypted
  • TCP connectivity is verified before each agent launch

Build Integrity

  • Deterministic builds with locked NuGet restore (packages.lock.json)
  • Embedded PDB symbols (no separate symbol files to tamper with)
  • SHA256 checksums published for all release artifacts
  • Single-file self-contained deployment (no external DLLs to substitute)

Automated Security Scanning

Six security scans run on every push and pull request (Dependency Review is a pull-request gate only), each also on a weekly schedule:

Scanner What it checks
CodeQL Static application security testing (SAST) for C# and GitHub Actions workflow YAML
Semgrep Pattern-based SAST and secret detection
Gitleaks Git history scanning for leaked secrets
PSScriptAnalyzer PowerShell script security rules
Dependency Review CVE gate on pull requests (blocks known-vulnerable dependencies)
Trivy Software composition analysis (NVD, GHSA, OSV databases)

Dependencies

JenkinsAsService depends on third-party NuGet packages. We monitor these via:

  • Dependabot — automated pull requests for version updates
  • Dependency Review — blocks PRs that introduce known CVEs
  • Trivy SCA — scans resolved dependencies against multiple vulnerability databases

If you discover a vulnerability in a dependency, please report it to the package maintainer. If the vulnerability is exploitable through JenkinsAsService specifically, report it to us as well.

Bounties

This is a personal open-source project. All work is done on a volunteer basis. We are unable to offer monetary bounties for security reports. We do offer public credit in the advisory if desired.

There aren't any published security advisories