📦 Marketplace status: Live on the GitHub Marketplace. Use it via
uses: ASCIT31/darkmoon-action@v1(recommended, moving major tag), or pin a release withuses: ASCIT31/darkmoon-action@v0.1.0.
Darkmoon is open-source — a star really helps us grow.
🌐 Website: dark-moon.org · 📚 Docs: docs.dark-moon.org · ⭐ Star the core: github.com/ASCIT31/Dark-Moon
Install the integrations, right where you work:
| Platform | Get it |
|---|---|
| VS Code | VS Code Marketplace |
| JetBrains | JetBrains Marketplace |
| GitHub Actions | GitHub Marketplace |
| GitLab CI/CD | CI/CD Catalog |
| Jenkins | Download the .hpi |
| Client & CLI | npm: @darkmoon_ai/client |
Generated by running the real bundled action (dist/index.js) against the
synthetic Demo Shop campaign (demo-shop.local, zeroed secrets), then
rendering the exact output it writes.
Job summary ($GITHUB_STEP_SUMMARY) — the verbatim markdown the action
writes, rendered with GitHub-flavored-markdown styling. Aggregate counts only;
no evidence, endpoints or tokens:
Code scanning alerts (SARIF) — with report-format: sarif the action
synthesizes SARIF from the findings; uploaded via github/codeql-action/upload-sarif
it appears under Security → Code scanning. Below is a representative render of
the real generated .sarif (the live GitHub.com alerts UI needs a repository):
- Masks your token / password with
core.setSecret()before first use. - Detects the edition (Pro via
GET /api/v1/system/info, else OSS). - Launches an assessment (or attaches to an existing campaign via
campaign-id). - Tracks it to completion — SSE on Pro, polling on OSS. A run still not
terminal past
timeout-msis treated as failure, never a pass. - Fetches the severity summary + findings + report.
- Writes a severity table to the job summary (
$GITHUB_STEP_SUMMARY). - Fails the job from FINDINGS (never from an exit code) per
fail-on.
- Nothing sensitive is printed. Tokens, licenses, credentials and finding evidence never reach the log. Secrets are masked; strings are scrubbed twice.
- Redaction-safe by default. The report artifact is the client's redacted
body; the findings JSON has
evidence: nulland the backendrawobject is stripped. Un-redacted output is a deliberate two-key opt-in (full-report). - Nothing is posted to shared surfaces unless you ask.
post-reportisfalseby default. When enabled, only aggregate severity counts are posted to the PR/commit — never evidence, endpoints, or the report body. - Findings-based verdict.
fail-onis evaluated from finding counts via the client'scomputeFailPolicy; the OSS CLI exits0even with criticals, and the action ignores exit codes entirely.
- uses: ASCIT31/darkmoon-action@v1
with:
mode: oss
oss-data-dir: /opt/darkmoon/darkmoon-settings # host bind-mount with campaigns/ + vulnerabilities/
oss-reports-dir: /opt/darkmoon/reports
oss-launch-template: docker,exec,-T,opencode,opencode,run,--agent,pentest,--format,json,{PROMPT}
target: http://127.0.0.1:3000
focus: sqli,xss,idor
fail-on: critical,highRun one Darkmoon container / compose-project per CI job: OSS runs share one data dir and the client correlates the new campaign by snapshot-diff.
- uses: ASCIT31/darkmoon-action@v1
with:
mode: pro
base-url: ${{ vars.DARKMOON_BASE_URL }}
api-token: ${{ secrets.DARKMOON_API_TOKEN }}
target: https://staging.example.com
fail-on: critical
post-report: truePro also accepts username + password instead of api-token (the action then
obtains a JWT). When the Pro admin still has the default password
(must_change_password), detection fails closed with an insecure-default error;
set refuse-insecure-default: false only to downgrade it to a warning.
Viewing findings. After the run, the severity table and any warnings appear
in the workflow step summary; machine-readable results are exposed as action
outputs (critical/high/…, campaign-id, policy-failed) and, with
report-format: sarif, in the repository's Security → Code scanning tab.
Darkmoon has no native SARIF; the action synthesizes it from findings.
- uses: ASCIT31/darkmoon-action@v1
id: dm
with: { target: http://127.0.0.1:3000, report-format: sarif }
- uses: github/codeql-action/upload-sarif@v3
if: always()
with: { sarif_file: ${{ steps.dm.outputs.report-path }} }- uses: ASCIT31/darkmoon-action@v1
with:
mode: oss
oss-data-dir: /opt/darkmoon/darkmoon-settings
campaign-id: camp_20260728_9018be77
fail-on: critical,highjobs:
security:
uses: ASCIT31/darkmoon-action/.github/workflows/darkmoon-reusable.yml@v1
with:
target: http://127.0.0.1:3000
fail-on: critical,high
secrets:
api-token: ${{ secrets.DARKMOON_API_TOKEN }}Transport: mode (auto|oss|pro), base-url, api-token, username,
password, refuse-insecure-default, oss-data-dir, oss-reports-dir,
oss-script-path, oss-launch-template.
Scope (maps to the Darkmoon prompt DSL): target, targets, program,
focus, severity (max cap), exclude, out-of-scope, noise, format,
safe-harbor, rules.
Policy & reporting: fail-on, report-format (markdown|json|sarif),
report-dir, full-report, post-report, github-token, campaign-id,
poll-interval-ms, timeout-ms.
See action.yml for the full list and defaults.
campaign-id, edition, overall-risk, total-findings, critical, high,
medium, low, info, exploited, confirmed, unconfirmed, remediated,
report-path, policy-failed.
npm ci
npm run typecheck
npm test # unit + integration (mocked client)
npm run build # bundle to dist/index.js (esbuild)The bundled dist/index.js is committed (GitHub Actions runs it directly). CI
verifies it is up to date. Real E2E scenarios live in scripts/e2e-run.sh.
MIT © 2026 ASC-IT (SARL) / Darkmoon. See LICENSE.

